home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / oberguid.zip / OBERGUID.DOC < prev   
Text File  |  1992-07-31  |  131KB  |  3,452 lines

  1.  
  2. The Oberon Guide 
  3.  
  4. System Release 1.2 
  5.  
  6. Jurg Gutknecht 
  7.  
  8.  
  9. Abstract 
  10.  
  11. This guide provides a concise and detailed description of the Oberon system
  12. on three different levels: the user's level, the level of programmers of
  13. tools, and the level of implementors of new viewer classes. In particular,
  14. the guide features a complete documentation of standard commands, a commented
  15. series of important interface definitions, and a tutorial collection of Oberon
  16. programs exemplifying the typical Oberon programming style.
  17.  
  18.  
  19. Table of Contents 
  20.  
  21. Abstract 
  22.  
  23. Introduction 
  24.   History
  25.   Design Principles
  26.   Acknowledgement
  27.  
  28. User's Guide 
  29.   Commands and Tools
  30.   The Edit Tool Package
  31.   The Draw Tool Package
  32.   The Paint Tool Package
  33.   The System Tool Package
  34.   The Compiler Tool Package
  35.   The Miscellaneous Tool Package
  36.   The Backup Tool Package
  37.   The Net Server Tool Package
  38.   The ColorSystem Tool Package
  39.  
  40. Guide for Programmers of Commands 
  41.   Oberon's module hierarchy
  42.   The Display System
  43.   The Text System
  44.   The Oberon Core
  45.   Tutorial Examples
  46.     Write time stamp to system log
  47.     Process selected text
  48.     Open viewer in system track, generate, and display text data
  49.  
  50. Open viewer in user track and display existing text 
  51.   Grow text viewer
  52.   Process viewer text or sequence of texts, depending on context
  53.  
  54. Delete selected part of text in marked viewer 
  55.   Copy most recently selected text part to caret's position
  56.   Copy font from visibly marked position to text selection
  57.   Move caret to next character written in italics
  58.  
  59. Guide for Programmers of new Frame Classes and Viewer Types 
  60.   Frames as Active Objects
  61.   Standard Menu Viewers
  62.   The Canonical Decomposition of an Application
  63.   Tutorial Examples 1: Frame oriented operations
  64.     Display text line within text frame
  65.     Track caret
  66.   Tutorial Examples 2: Text oriented operations
  67.     Save text in buffer
  68.     Insert contents of buffer in text
  69.  
  70. Literature 
  71.   Ceres Workstation
  72.   Oberon Language
  73.   Oberon System
  74.  
  75. List of Oberon Error Numbers 
  76.   Incorrect use of language Oberon-2
  77.   Limitations of implementation
  78.   Run-time Trap Numbers
  79.  
  80.  
  81. Introduction 
  82.  
  83.  
  84. History 
  85.  
  86. Oberon is simultaneously the name of a project and of its outcome. The
  87. project was started by Niklaus Wirth and the author late in 1985 with
  88. the goal of developing a modern and portable operating system for
  89. personal workstations. Its results are an implementation of the system
  90. for the Ceres computer and a programming language (see section Literature).
  91.  
  92. The development of the language Oberon needs perhaps a short justification.
  93. It became quite inevitable because the type-system of available languages
  94. turned out to be too restrictive to express the desired data model in a
  95. natural and safe way. We refer to report for a definition of the new language,
  96. and to the third and fourth chapter of this text for some examples of its
  97. application.
  98.  
  99.  
  100. Design Principles
  101.  
  102. For the present, we focus on the system Oberon, beginning with a brief
  103. overview of its design principles. The underlying dynamic model is extremely
  104. simple. There exists a single process acting as a common carrier of multiple
  105. tasks. This process repetitively interprets commands , which are the official
  106. entities of execution in Oberon. Commands are atomic actions operating on the
  107. global state of the system. Unlike customary interactive programs, they
  108. rigorously avoid direct dialogs with the system user.
  109.  
  110. The following typical examples indicate the bandwidth covered by the concept 
  111. of command: Placing the caret, inserting a character into a text, selecting
  112. a piece of text, deleting a selected piece of text, applying a new font to a
  113. piece of text, searching a pattern in a text, compiling a software module,
  114. opening a viewer, backing up a sequence of files to diskette, and displaying
  115. a directory. We emphasize that the execution of a command always results in
  116. non-volatile information. For example, in the last example, this means that
  117. the displayed directory is a text that might immediately undergo further
  118. processing. Typically, commands report the outcome of their execution in
  119. the form of an entry in the system-log . Therefore, the log provides a
  120. complete protocol of the current session.
  121.  
  122. Commands are initiated by input actions. Apart from a few universal operations,
  123. every input action is connected with a displayed viewer , to which its further
  124. handling is delegated. A viewer in Oberon is a rectangular area on the screen
  125. that can display any kind of data. Most viewers feature a thin frame and a
  126. title-bar containing a menu. Any mouse-oriented input is handled by the viewer
  127. the mouse points to. Data from the keyboard is immediately passed over to the
  128. current so-called focus-viewer . We notice that command interpretation is a
  129. highly decentralized activity in Oberon and, as such, is a substantial
  130. contribution to what we consider as Oberon's most important quality, namely
  131. unlimited extensibility. 
  132.  
  133. Implementing a new viewer type is a very powerful but also quite far-reaching 
  134. method to extend the Oberon system. It is only appropriate in conjunction with
  135. the installation of a new class of displayable objects (for example graphics
  136. or tables). The fourth chapter will provide more insight into this topic.
  137.  
  138. A more moderate way to increase the system's functionality consists in
  139. adding new commands operating on objects of an already existing class
  140. (for example a language compiler operating on text). We shall see in
  141. the third chapter that Oberon's open and coherent modular architecture
  142. provides effective support for that. Practically all system ingredients
  143. and resources are directly accessible and usable via modular interfaces
  144. on as high a level of abstraction as possible.
  145.  
  146. We should deduce from the foregoing that there is no symbolic wall in
  147. Oberon separating actual users from developers. Users are encouraged
  148. to customize the system and tailor it to their individual needs by
  149. designing and implementing private commands and facilities. Little is 
  150. "hardwired" in the system. However, there are several general conventions
  151. and existing tools. They are presented in the next chapter.
  152.  
  153.  
  154. Acknowledgement 
  155.  
  156. I gratefully acknowledge Niklaus Wirth's initiative and willingness for 
  157. travelling through the adventures of designing and building a new workstation,
  158. a new language, and a new operating system, escpecially under the given severe
  159. restrictions of personal resources. Without his competence and extraordinary
  160. commitment this mammoth-project could not have been successfully completed.
  161. I am also very grateful for the possibility to include an extract of Niklaus
  162. Wirth's Draw guide in the first chapter. My thanks further go to the Oberon
  163. user's community, in particular to Martin Reiser, Hans-Peter Mossenbock, and
  164. Beverly Sanders for their constructive critisism and valuable suggestions for
  165. improvements. 
  166.  
  167.  
  168. User's Guide
  169.  
  170.  
  171. Commands and Tools 
  172.  
  173. Among the classes of possible objects to be handled by a computer system the 
  174. class of texts plays a key role. Not only are input and output data frequently
  175. represented as text, but also objects and commands are often identified by
  176. their name. Text is, therefore, a predefined class of objects in Oberon.
  177.  
  178. This manifests itself immediately after system startup, when, besides of the
  179. log-viewer , a so-called tool viewer is automatically opened on the screen.
  180. It contains a list of command names, some of them followed by parameters.
  181. Command names in Oberon are of the form M.P, where M designates a module
  182. (package) and P a procedure (operation) that is provided by the module.
  183. A user activates a command simply by pointing to its name with the mouse
  184. and clicking the middle mouse key. For example, activating the command Edit.
  185. Open will result in a new viewer showing some default text. More often than
  186. not, the execution of a command is parameterized. For example, the opening of
  187. another tool needs the specification of its name, as in System.Open Edit.Tool
  188. or in System.Open Net.Tool. Although typical, this is not by far the most
  189. general case of a parameter specification. Some commands accept an entire
  190. list of names following the command name and execute repeatedly for each
  191. member of the list. In principle, a text obeying an arbitrary syntax
  192. (understood by the command) could be passed over equally well. Commands
  193. may even expect as parameters objects of any kind currently existing in the
  194. system such as viewers, text selections, caret, and a global star-shaped 
  195. pointer. Some commands even allow different ways of paramewter specification.
  196. For example, if System.Open or Edit.Open is called with a "^"-symbol instead
  197. of a file name following the command name, then the file name is taken from
  198. the most recent selection. In general, a "^"-symbol following a command name 
  199. always refers to the current selection.
  200.  
  201. It is noteworthy that tools are ordinary texts distinguishing themselves from 
  202. more usual texts only by their structure and contents. In particular, tools
  203. are amenable to editing operations. Looking at this differently, we recognize
  204. that commands like Edit.Open Explanations.Text may well slip into a prose text
  205. and be activated directly in situ. Obviously, no limits are set to fantasy 
  206. exploiting this universal scheme of command interpretation.
  207.  
  208. One rather moderate application of the universal scheme discussed above is the 
  209. construction of interconnected texts. As a matter of fact, the set of standard
  210. tools is structured as a tree with the System.Tool as ancestor and the tools
  211. listed in the System.Tool as its descendants. We recall that the hierarchical
  212. tool system may easily be customized on the fly by adjusting command lists
  213. (including parameters) to personal requirements, reconfiguring the tool
  214. hierarchy, installing new tools, or even providing on-line documentation.
  215.  
  216. We now discuss editing operations. Recall first that most commands are
  217. interpreted individually by viewers. There are, however, a few more universal
  218. operations, which are handled directly by the central system. For example,
  219. when you type escape, all marks on the display are removed, including caret
  220. and text selections. Or, when you type ctrl shift del the system immediately
  221. terminates the execution of the current command and opens a trap-viewer
  222. displaying the state of the interrupted process. Notice that we have just
  223. identified you as the reader of this guide with a user of the system. In
  224. order to simplify phrasing, we shall henceforth occasionally do so tacitly.
  225.  
  226. Next we turn to viewers and display-specific operations. You can put your 
  227. primary display screen into any one of three different modes by hitting one
  228. of the function keys PF1, PF2, and PF3. PF1 specifies white script on a black
  229. background, PF2 turns the display off, and PF3 specifies black script on a
  230. white background. Oberon uses a tiling viewer system. The display is divided
  231. into vertical tracks, and each track is further subdivided into viewers. In
  232. reality, the structure of viewers is three-dimensional. A new track may in
  233. fact overlay one or, more generally, an integral number of existing tracks.
  234. The original configuration will be reestablished when the overlaying track
  235. is later removed.
  236.  
  237. Although the global screen layout can be changed, we relate our current 
  238. explanations to the standard layout showing two tracks, a larger user track
  239. on the left and a narrower system track on the right. In principle, viewers
  240. are allocated automatically by the respective commands using a little
  241. heuristics. For example, tool viewers are opened in the system track, and
  242. document viewers in the user track. However, you can override any automatic
  243. allocation by first placing the pointer at the location where you desire the
  244. top of the new viewer to be placed. The pointer is a star-shaped marker, and 
  245. it is placed by moving the mouse to the desired location and then hitting the
  246. SETUP key. In order to change the size of an existing viewer, simply point to
  247. its title-bar, press the left mouse key, and move the mouse up or down
  248. accordingly. You can also conveniently move a viewer to any different place on 
  249. the display screen by starting exactly as just explained, then interclicking
  250. the middle mouse-key, dragging the mouse to the new location, and releasing
  251. all keys there.
  252.  
  253. Interclicking means clicking (pressing and releasing) a secondary mouse button 
  254. at an arbitrary time while a primary mouse key is being held down. In general,
  255. interclicking is an efficient and versatile tool to multiply the expressiveness
  256. of the mouse. In Oberon, interclicking is applied according to a systematic
  257. underlying pattern. You will find out more about this pattern in the following 
  258. chapters. Perhaps the easiest and most important rule says that the current
  259. command is nullified, if all remaining mouse-keys have been interclicked
  260. (not necessarily simultaneously) during the action.
  261.  
  262. By convention, most viewers (so-called menu-viewers) show a header consisting
  263. of a title and a list of selected commands (menu). These commands automatically
  264. refer to their own viewer. In the case of ordinary text viewers, commands are
  265. included from the System tool-package and the Edit tool-package. System.Close
  266. removes the viewer, Edit.Copy opens a new viewer displaying the same instance
  267. of text, Edit.Grow lets the viewer grow to the size of a full track or of the
  268. whole display, Edit.Locate locates a text position, and Edit.Store stores the
  269. text on file.We shall explain these commands in greater detail in the following
  270. sections on tools.
  271.  
  272. First, we fix some terminology and general conventions. We shall call marked
  273. an object or a location if it is visibly or invisibly marked by the earlier
  274. introduced star-shaped pointer. Visibility of the pointer is irrelevant in
  275. most cases. As an exception we mention the explicit allocation of a viewer,
  276. which requests the pointer to be visible. Note that an explicitly allocated
  277. viewer is automatically marked. Also note that the pointer is initially
  278. invisible and placed in the lower left corner of the display.
  279.  
  280. By convention, the title of a viewer is normally either the name of the 
  281. displayed object or the name of the command that opened this viewer. Further,
  282. if a list of names is passed to a command as a parameter, it must be terminated
  283. by a symbol other than a name, for example by the character "~". By another
  284. convention, the upper right corner of the display is reserved for the log
  285. viewer reporting on the progress and result in the execution of a command.
  286. Finally, there are several default extensions of file names. Among them are
  287. Text, Graph and Pict for file copies of texts, graphics, and bitmap pictures
  288. respectively, and Scn.Fnt for screen font files.
  289.  
  290. In the following sections we shall use the terms parameter and parameter
  291. list in the restricted sense of "item following the command name" and "list
  292. of items following the command name" respectively.
  293.  
  294.  
  295. The Edit Tool Package 
  296.  
  297. We have stated earlier that extensibility was a key objective in the design
  298. of Oberon. It was therefore enticing to realize also system-oriented commands
  299. as extensions of the system-core on a highest possible level in the modular
  300. hierarchy, thereby achieving maximal flexibility. Such a strategy is
  301. particularly appropriate for text editing. It manifests itself in the
  302. existence of an edit tool package providing an extensible set of powerful
  303. editing commands. Nevertheless, several built-in commands are interpreted
  304. directly by text frames. They include positionning the text within its viewer,
  305. placing the caret, inserting a typed character, selecting a part of text,
  306. deleting a selected part of text, copying a selected part of text, copying
  307. attributes and, most importantly, executing an arbitrary command which is
  308. specified by its name. We should point out that all of these built-in commands
  309. are applicable in particular to menu-bars (which, in fact, are ordinary text
  310. frames featuring an inverted background color).
  311.  
  312.  
  313. Mouse Commands 
  314.  
  315. Text positionning. In order to reposition a text within a viewer, move the 
  316. mouse into the viewer's scrolling-zone. This is a vertical bar along the
  317. left borderline of about 0.5 cm width. You can scroll forward by pressing
  318. the left mouse key, moving the mouse, and releasing the key when the text
  319. line that you want to become the top line is underlined. Notice that every
  320. text viewer shows a small crossbeam indicating the current position of the
  321. displayed section within the entire text. You can position a text directly
  322. by clicking the middle mouse key at the location where you want the
  323. crossbeam to be. If you wish the beginning of the text to be displayed, you
  324. can alternatively simply click the right mouse key anywhere within the
  325. scroll-bar.
  326.  
  327. Placing the caret. If you want to place the caret, move the mouse to the 
  328. desired text, press the left mouse button and, while keeping it down, move
  329. the caret to the desired position. Any subsequently typed characters are
  330. then inserted at this position.
  331.  
  332. As a side remark notice that German Umlaute are entered by pressing the
  333. following combinations of keys: ctrl a for ae, ctrl shift a for Ae, ctrl o
  334. for oe, ctrl shift o for Oe, ctrl u for ue, and ctrl shift U for Ue.
  335.  
  336.               A  O  U       (a umlaut represented by ae, etc.)
  337.  -            a  o  u
  338.  shift        A  O  U
  339.  ctrl        ae  oe  ue
  340.  shift ctrl  Ae  Oe  Ue
  341.  
  342. Selecting text. You can select any contiguous stretch of text by moving the 
  343. mouse to the desired beginning, pressing the right mouse button and, while
  344. holding it down, dragging the selection to the end. If you click twice at
  345. the beginning, the selection is automatically extended to the origin of
  346. that text line. If a piece of text is too large to be selectable within
  347. a single viewer, use Edit.Copy to open an adjacent second viewer. Then
  348. select the beginning of the stretch of text in the upper viewer and its
  349. end in the lower viewer separately. Note that a separate selection may
  350. be active for each displayed text section, including headers of viewers.
  351. If several selections exist simultaneously on the display, commands
  352. normally refer to the most recent one or to the most recent ones. 
  353.  
  354. There are the following interesting interclick-variants of caret placing and 
  355. text selection that combine these marking operations effectively with text
  356. editing. Remember the general rule saying that any mouse-controlled operation
  357. that is currently under execution can be nullified by interclicking all
  358. remaining mouse-keys. 
  359.  
  360. Copying text. If you interclick the middle mouse button while you are placing 
  361. the caret, the most recent selection is automatically copied to the caret's
  362. position as soon as you release the left button. This feature is particularly
  363. convenient for copying a specific template to several different places.
  364. Alternatively, if the caret is already set and you click the middle mouse key
  365. while you are selecting a piece of text, the selected text is copied to the
  366. caret's position when you release the select-button. This option is most
  367. conveniently used in order to copy a given string to various places. In order 
  368. to neutralize (undo) any "interclick", simply click the remaining third button
  369. while still holding down the primary key.
  370.  
  371. Copying attributes. If you interclick the right mouse button while you are 
  372. placing the caret, the character attributes (font, color, vertical offset) of
  373. the character by the caret is automatically applied to the most recent
  374. selection as soon as you release the left button.
  375.  
  376. Deleting text. If you click the left mouse-button while selecting a text, the 
  377. selected text is eventually deleted. Here also, the interclick can be undone
  378. by an additional interclick of the middle mouse-key.
  379.  
  380. Notice that the above described editing operations are applicable to a header 
  381. of a viewer only restrictedly.A header cannot be changed. Nor can the caret be
  382. placed in a header. Further notice that the copy variant and the delete variant
  383. of the select command apply also in the case of large selections involving
  384. split viewers.
  385.  
  386. Activating a command. Activating a named command from within a text viewer is
  387. generic and therefore the most general built-in operation. In order to do it
  388. simply point to the command's name and click the middle mouse key. Sometimes
  389. (e.g. in a test phase) it is important that the newest version of the module
  390. providing the desired command is loaded before the command is actually
  391. executed. In order to force this, simply interclick the left key while you
  392. are pressing the middle mouse key and pointing to the command's name.
  393.  
  394. If command execution fails, the system falls into a trap. There is no
  395. interactive debugger currently available under Oberon. However, a trap handler
  396. is automatically called whenever a trap has occurred. It displays the state of
  397. the interrupted process, including the stack of procedure activations. It also
  398. relates the location of trap to a position in the source program text. In order
  399. to find the failing statement simply display the source program and mark its
  400. viewer. Then select the position number in the trap viewer and invoke
  401. Edit.Locate.
  402.  
  403. The following table summarizes the basic meanings of the three mouse-keys:
  404. The left key is the point-key. It is used to focus a certain location,
  405. i.e. to place the caret. The middle key is the execute-key. Pressing and
  406. releasing it causes the appropriate command interpreter to be called. The
  407. right key is the select-key. It is used to select objects within a viewer.
  408.  
  409. Summary of mouse commands 
  410.  
  411.    primary button      left            middle         right
  412.    ---------------------------------------------------------------
  413.    secondary
  414.    button
  415.  
  416.    none              set caret         execute        select
  417.  
  418.    left                 -              free and       delete
  419.                                        execute
  420.  
  421.    middle          copy selection         -           copy this
  422.                                                       selection
  423.  
  424.    right           copy attributes   -                    -
  425.  
  426.  
  427. Text viewers display text in a standard line-oriented way. In particular,
  428. they do not support any non-trivial formatting, such as automatic line-
  429. breaking or right-justifying paragraphs, for example. Font variation, color
  430. specification, and vertical offset, are however possible. We recommend the
  431. following fonts to be used in connection with text viewers: Syntax10.Scn.Fnt
  432. (default font), Syntax10i.Scn.Fnt (italics variant), Syntax10b.Scn.Fnt
  433. (bold face variant), and Courier8.Scn.Fnt (non-proportional font).
  434.  
  435. According to Oberon's basic scheme, additional functionality is provided by 
  436. the text edit tool package. It contains the following commands.
  437.  
  438.  
  439. Edit Commands 
  440.  
  441. Edit.Open 
  442. opens a viewer in the user track displaying the specified text. The text is 
  443. alternatively specified by a parameter on the command line or, if a "^"-symbol
  444. follows the command name, by the most recent selection of a name. If none
  445. exists, a default name is taken. In order to override automatic allocation,
  446. place the pointer anywhere on the screen. 
  447.  
  448. Edit.Show M.X 
  449. opens a viewer in the user track displaying the specified object X of module
  450. M. If the implementation of M is available, the implementation of X is shown,
  451. otherwise X 's definition is displayed.
  452.  
  453. Edit.Store 
  454. writes the text in the marked viewer to the file with the name defined by the 
  455. parameter, or, if called from the menu line of a text viewer, writes the
  456. displayed text to the file with the name of the viewer.
  457.  
  458. Edit.Recall 
  459. inserts the most recently deleted piece of text at the position of the caret. 
  460.  
  461. Edit.CopyFont 
  462. transfers the font from the marked location to the most recent text selection. 
  463.  
  464. Edit.ChangeFont 
  465. applies the font specified by the parameter to the most recent text selection. 
  466.  
  467. Edit.ChangeColor
  468. applies the color specified by the parameter to the most recent text selection. 
  469.  
  470. Edit.ChangeOffset 
  471. applies the vertical offset specified by the parameter to the most recent text 
  472. selection. 
  473.  
  474. Edit.Search 
  475. searches a pattern in the marked text. The pattern is defined by the most 
  476. recent text selection. If none exists, the previous pattern is used. Searching
  477. is started at the position of the caret. If none exists in the marked text,
  478. searching starts at the beginning. The initial value of the pattern is the
  479. space character.
  480.  
  481. Edit.Locate 
  482. positions the text in the marked viewer according to the position-number 
  483. indicated by the most recent text selection. Leading non-numerical items
  484. in the text selection are ignored.
  485.  
  486.  
  487. Edit.Print ServerName ["%"] { (TextFileName | "*") ["/" NofCopies] } 
  488. sends all texts specified by the parameter list to the print server whose name
  489. is taken from the first entry in the parameter list. Names in the parameter
  490. list refer to text files, the symbol * to the text in the marked viewer. The
  491. symbol % specifies the vanilla-print option. If active, the texts are printed
  492. in a single monospaced small Font (Gacha10l). This option is typically used
  493. for printing source program listings. NofCopies optionally specifies the
  494. desired number of copies. It must be a single-digit number. This command
  495. assumes that the correct user identification has previously been installed
  496. (by calling System.SetUser ).
  497.  
  498.  
  499. The Draw Tool Package 
  500.  
  501. The system called Draw serves to prepare line drawings. They contain lines,
  502. text captions, and other items, and are displayed in graphic viewers (more
  503. precisely: in menu viewers' graphic frames). A graphic viewer shows an
  504. excerpt of the drawing plane, and several viewers may show different parts
  505. of a drawing.
  506.  
  507. The most frequently used commands are built-in as mouse clicks and combinations
  508. of clicks. Additional commands are selectable from texts, either in viewer's
  509. menus (title bar) or in the text called Draw.Tool. The mouse buttons have the
  510. following principal functions;
  511.  
  512.      left   :     draw
  513.      middle :     move/copy
  514.      right  :     select
  515.  
  516. A mouse command is identified (1) by the button k0 pressed initially, (2) by 
  517. the initial position P0 of the cursor, (3) by the set of keys k1 of buttons
  518. pressed until the last is released, and (4) the cursor position P1 at the
  519. time of release.
  520.  
  521. The basic system consists of the modules Draw, GraphicFrames, and Graphics.
  522. These modules contain the facilities to generate and handle horizontal and
  523. vertical lines, text captions, and macros. Additional modules serve to
  524. introduce other elements, such as rectangles and circles, and the system is
  525. extensible, i.e. further modules may be introduced to handle further items.
  526.  
  527.  
  528. Basic Commands
  529.  
  530. The command Draw.Open (available in the Draw.Tool text) opens a new viewer
  531. and displays the graph with the name given as parameter. If no parameter is
  532. specified with the command, the last text selection is taken as parameter.
  533. We suggest that file names use the extension Graph.
  534.  
  535. Drawing a line. In order to draw a horizontal or vertical line from P0 to P1, 
  536. press the button with the cursor at P0 and, while holding the button, move
  537. the mouse and cursor to P1. Then release the button. If P0 and P1 differ in
  538. both their x and y coordinates, the end point is adjusted so that the line
  539. is either horizontal or vertical.
  540.  
  541. Writing a caption. First place the cursor where the caption is to appear. Then 
  542. click the left button, causing a crosshair to appear. This is called the caret.
  543. Then type the text. Only single line texts are accepted. The DEL key may be
  544. used to retract characters (backspace).
  545.  
  546. Selecting. Most commands require the specification of operands, and many 
  547. implicitly assume the previously selected elements - the selection - to be
  548. their operands. A single element is selected by pointing at it with the cursor
  549. and then clicking the right mouse button. This also causes previously seleted
  550. elements to be deselected. If their selection is to be retained, also click
  551. the left button. This action is called an interclick. If you wish to select
  552. several elements at once, move the cursor from P0 to P1 while holding the
  553. right key. Then all elements lying within the rectangle with diagonally
  554. opposite corners at P0 and P1 are selected.
  555.  
  556. Selected lines are displayed as dotted lines, selected captions (and macros) 
  557. by inverse video mode. A mocro is selected by pointing at its lower left corner.
  558.  
  559. Moving. If you wish to move (displace) a set of elements, first select them, 
  560. and then move the cursor from P0 to P1 while holding the middle button. The
  561. vector from P0 to P1 specifies the movement and is called the displacement
  562. vector. P0 and P1 may lie in different viewers displaying the same graph.
  563.  
  564. Copying. Similarly, the selected elements may be copied (duplicated). In 
  565. addition to pressing the middle button while indicating the displacement
  566. vector, interclick the left button.
  567.  
  568. The copy command may also be used to copy elements from one graph into another 
  569. graph by moving the cursor from one viewer into another viewer displaying the
  570. destination graph.
  571.  
  572. A text caption may be copied from a text frame into a graphic frame and 
  573. vice-versa. There exist two ways to achieve this:
  574.  
  575. 1. First place the caret at the destination position, then select the text
  576.    and interclick the middle button.
  577.  
  578. 2. First select the text to be copied, then place the caret at the destination
  579.    point by clicking the left and interclicking the middle button.
  580.  
  581. Shifting the plane. You may shift the entire drawing plane behind the viewer 
  582. by specifying a displacement vector pressing the middle button (like in a move
  583. command) and interclicking the right button.
  584.  
  585. Moving and resizing a viewer. A viewer can be enlarged or shrunk by placing 
  586. the cursor into the title bar and then moving it, while holding the left
  587. button to the desired new position. If the viewer is to be moved, additionally
  588. interclick the middle button.
  589.  
  590. The following table shows a summary of the mouse actions: 
  591.  
  592.   primary button:       left           middle    right
  593.   interclick:
  594.      none       draw line/set caret     move     select
  595.      left                -              copy     select
  596.      middle          copy text           -       copy text
  597.      right          shift plane          -         -
  598.  
  599.  
  600. Menu Commands
  601.  
  602. The following commands from the tool package Draw are displayed in the menu
  603. (title bar) of every graphic viewer. They are activated by being pointed at
  604. and by clicking the middle button.
  605.  
  606.    Draw.Cleanup   The entire drawing is repainted.
  607.  
  608.    Draw.Delete    The selected elements are deleted.
  609.  
  610.    Draw.Store     The drawing is written as file with the name shown in
  611.                   the title bar. The original file is renamed by changing
  612.                   its extension to Bak.
  613.  
  614. The subsequent commands pertain to attributes of drawing elements, such as 
  615. line width, text font, and color. The Set-commands determine the respective
  616. attributes of subsequently created elements, the Change-commands to those of
  617. the current selection in the marked viewer.
  618.  
  619.     Draw.SetWidth w           Default width = 1,  0 < w < 7.
  620.     System.SetFont fontname   Default = Syntax10.Scn.Fnt
  621.     System.SetColor c         Default = white
  622.     Draw.ChangeWidth w        (0 < w < 7)
  623.     Draw.ChangeFont fontname
  624.     Draw.ChangeColor c
  625.  
  626. The SetColor and ChangeColor commands either take a color number in the range 
  627. 1.. 15 or a string as parameter. The latter case serves to select the color
  628. from the character immediately following the caret position (see Draw.Tool).
  629.  
  630.  
  631. Macros
  632.  
  633. A macro is a (small) drawing that can be identified as a whole and be used
  634. as an element within a (larger) drawing. Macros are typically stored in
  635. collections called libraries, from where they can be selected and copied
  636. individually.
  637.  
  638.    Draw.Macro lib mac     The macro mac is selected from the library
  639.                           named lib and inserted in the drawing at the
  640.                           caret's position. It is automatically selected
  641.                           and shown in inverse video.
  642.  
  643.    Draw.Directory         libfile Lists the macro names contained in
  644.                           the named library file.
  645.  
  646. The following commands are used when new macros are to be constructed and 
  647. inserted in a (possibly new) library.
  648.  
  649.    Draw.OpenMacro lib mac   The elements of macro mac from library lib
  650.                             are inserted at the caret's position. They
  651.                             can now be selected individually.
  652.  
  653.    Draw.MakeMacro lib mac   1. Select all elements that are to belong to
  654.                                the new macro.
  655.                             2. Set the caret where the macro's origin is
  656.                                to be.
  657.                             3. Place a secondary caret at the macro's
  658.                                opposite corner by using the left button
  659.                                and interclicking the right button.
  660.                             4. Activate the MakeMacro command. The macro
  661.                                is added to the library lib and carries
  662.                                the name mac.
  663.  
  664.  
  665. Further Commands
  666.  
  667. The following commands are listed in the text Draw.Tool, but may appear in
  668. any text.
  669.  
  670.     Draw.Reset                 The drawing plane in the marked viewer (*) is
  671.                                reset such that the plane's origin lies in the
  672.                                lower left corner.
  673.  
  674.  
  675.     Draw.Store name            The drawing in the marked viewer is stored as
  676.                                a file with the specified name.
  677.  
  678.     Draw.Print Servername *    The drawing in the marked viewer is printed by
  679.                                the named print server.
  680.  
  681.     Draw.Print Servername { Filename }. The named files are printed.
  682.  
  683.     Draw.SetGrid n             Inside graphic viewers, the cursor moves in
  684.                                discrete steps on an invisible grid. The
  685.                                distance between grid points is initially 4
  686.                                pixels; it can be set by this command to 2 - n
  687.                                pixels (0 <= n < 4).
  688.  
  689.     Draw.CarPos                Displays the numeric coordinates of the
  690.                                caret in the log viewer.
  691.  
  692.     Draw.MakeLib lib filename  The library lib is written as a file.
  693.                                Important Note: The written collection of
  694.                                macros contains only those macros that had
  695.                                previously been inserted by the commands
  696.                                Draw.Macro and Draw.MakeMacro. Hence, if
  697.                                new macros are to be added to an existing
  698.                                library file, the entire file must be read
  699.                                first by Draw.Macro applied to each existing
  700.                                macro element. This is typically done by
  701.                                opening a drawing containing all macros of
  702.                                the library file.
  703.  
  704. Macros are typically used for drawing electronic circuits. The basic library 
  705. file containing frequently used TTL circuits is called TTL0.Lib, and a drawing
  706. showing its elements is called TTL0.Graph.
  707.  
  708.  
  709. Rectangles
  710.  
  711. Rectangles can be created as individual elements and are frequently used as 
  712. frames around a set of other elements. They consist of four lines which are
  713. selectable as a unit. The attribute commands SetWidth, SetColor, ChangeWidth,
  714. and ChangeColor also apply to rectangles. Rectangles are selected by pointing
  715. at their lower left corner.
  716.  
  717.     Rectangles.New    1. Place the caret where a corner of the new rectangle
  718.                          is to lie (left button).
  719.                       2. Place a secondary caret where the opposite corner is
  720.                          to lie by interclicking the right button.
  721.                       3. Activate the command.
  722.  
  723. Rectangles may be filled with a shade pattern. The shade is specified as a 
  724. number s (0 # s # 9).
  725.  
  726.     Rectangles.SetShade s      default = 0: no shading
  727.                                Note: In the current implementation, all shades
  728.                                appear as the same pattern on the display but
  729.                                differ on the printer.
  730.  
  731.  
  732. Circles
  733.  
  734. Further graphic elements are circles and ellipses.
  735.  
  736.     Circles.New    1. Place the caret where the center is to lie.
  737.                    2. Place a secondary caret to the right of the center.
  738.                       This position will lie on the circle.
  739.                    3. Activate the command.
  740.  
  741. If another secondary caret is positioned above the center, an ellipse is 
  742. generated instead of a circle.
  743.  
  744.  
  745. Installing the Draw system
  746.  
  747. The following modules are needed to install the system: 
  748.     Draw.Obj   GraphicFrames.Obj   Graphics.Obj   Draw.Tool
  749.  
  750. If rectangles are to be used:
  751.     Rectangles.Obj
  752.  
  753. and if circles are to be used:
  754.     Circles.Obj   Display1.Obj
  755.  
  756. For drawing digital circuit diagrams, the following fonts and library is 
  757. required: (also Rectangles)
  758.     Syntax8.Scn.Fnt   Elektra.Scn.Fnt   TTL0.Lib
  759.  
  760. Furthermore, there exist the following files:
  761.     Symbols.Graph   TTL0.Graph
  762.  
  763.  
  764. The Paint Tool Package 
  765.  
  766. The Paint package serves the purpose of displaying and editing digitized 
  767. pictures. Its scheme of functionality and its user interface follow as
  768. closely as possible the lines of the text and graphic packages.
  769.  
  770.  
  771. The mouse-controlled built-in commands are these:
  772.  
  773. Summary of mouse-controlled commands 
  774.  
  775.  primary button           left              middle               right
  776.  ----------------------------------------------------------------------------
  777.  secondary button
  778.    none                 set caret      pen/selection move        select
  779.    left                    -               pen draw              delete
  780.    mid                copy selection           -                copyover
  781.    right              multiple caret        pen erase               -
  782.  
  783. The associated tool package augments the set of built-in picture editing 
  784. operations by the following commands.
  785.  
  786. Paint.Open {/w h} 
  787. opens a viewer in the user track displaying the specified picture. The picture 
  788. is alternatively specified by a parameter on the command line or by the most
  789. recent selection of a name. If none exists, the name Paint.Open is assumed as
  790. default.
  791.  
  792. Paint.Zoom 
  793. zooms in a picture to such a size that the most recent selection is completely 
  794. visible, or if no selection exists, zooms out the picture.
  795.  
  796. Paint.Print 
  797. prints the named file. It assumes that the correct user identification has 
  798. previously been installed. 
  799.  
  800. Paint.Scale 
  801. opens a copy of the current picture scaled to the size of the most recent 
  802. selection, or, if no selection exists, sized down to the size of the actual
  803. picture.
  804.  
  805. Paint.Draw vertical line / horizontal line
  806. draws a vertical (horizontal) line starting at the first caret and ending at 
  807. the second. 
  808.  
  809. Paint.SetColor | white | black | white invert
  810. applies the color specified by the parameter to subsequently executed 
  811. operations. 
  812.  
  813. Paint.SetPen w h 
  814. sets pen width and height to w and h. 
  815.  
  816. Paint.Fill n 
  817. fills an area with specified pattern. 
  818.  
  819. Paint.SetGrid n 
  820. sets the distance of grid points to n. Caret moves in discrete steps on the 
  821. specified grid. 
  822.  
  823. Paint.SetFont FontName 
  824. applies the font specified by the parameter to subsequently typed characters. 
  825.  
  826.  
  827. The subsequent sections conclude this chapter. They provide a concise
  828. functional description in tabular form of the most important currently
  829. available non-editing tools.
  830.  
  831.  
  832. The System Tool Package 
  833.  
  834. This package features system related commands. Among them are procedures to 
  835. display tools in the form of viewers, to close viewers and tracks, to define
  836. and display all kinds of system oriented parameters, and to provide basic
  837. utilities for the manipulation of named files. In addition, the system tool
  838. package contains a trap handler that is implicitly called after a trap has
  839. occured. It displays the current state of the system stack.
  840.  
  841.  
  842. System.Open 
  843. opens a viewer in the system track displaying the specified tool. The tool is
  844. alternatively specified by a parameter on the command line or, in the case of
  845. a "^" following the command name, by the most recent selection of a name. If
  846. none exists, a default name is taken.
  847.  
  848. System.OpenLog 
  849. opens a viewer in the system track displaying the system-wide log. Notice
  850. that the log is updated regardless of its visibility. Therefore, the log
  851. always shows the complete history of the current session.
  852.  
  853. System.Copy 
  854. opens a copy of the original viewer displaying the same instance of contents. 
  855.  
  856. System.Grow 
  857. lets the viewer grow to the size of a whole track or, if applied to a viewer 
  858. already filling a track, to the size of the whole display. Note that the
  859. original constellation will be reestablished when the grown viewer is
  860. later removed. 
  861.  
  862. System.Close 
  863. removes the marked viewer from the display, or, if called from the menu line 
  864. of a text viewer, removes the own viewer.
  865.  
  866. System.CloseTrack 
  867. closes the marked track, i.e. removes all viewers in this track. 
  868.  
  869. System.Recall 
  870. reopens the most-recently (perhaps erronously) closed viewer.. 
  871.  
  872. System.Time 
  873. displays the current date and time. If date and time parameters dd.mm.yy
  874. hh.mm.ss (day, month, year and hour, minute, second) immediately follow
  875. the command name, System.Time first sets date and time accordingly.
  876.  
  877. System.Watch 
  878. displays the amount of currently used disk space and memory resources. 
  879.  
  880. System.Collect 
  881. initiates a subsequent garbage collection. 
  882.  
  883. System.Free 
  884. unloads every module specified by the parameter list. If a module name is 
  885. immediately followed by *, imported modules are also unloaded.
  886.  
  887. System.ShowModules 
  888. displays a map of all currently loaded modules. 
  889.  
  890. System.ShowCommands ModName 
  891. displays a list of all commands exported by this module. 
  892.  
  893. System.State ModName 
  894. displays the global data of the specified module. 
  895.  
  896. System.SetUser 
  897. accepts the user's identification in the form UserName "/" Password without
  898. echoing it on the display. UserName is up to eight characters long (initials
  899. in most cases). The password is an arbitrary string.
  900.  
  901. System.Directory 
  902. displays the selection of all disk files whose name match the template 
  903. specified by the parameter. The parameter is a string and may contain the
  904. symbol "*" as a wildcard. If option "d" is specified ("/d" immediately
  905. following the parameter) additional information about file sizes and dates
  906. is displayed. In the case of a "^" following the command name the parameter
  907. is taken from the current selection.
  908.  
  909. System.CopyFiles 
  910. processes a parameter list of pairs A => B. Copies each file A to B. In the 
  911. case of a "^" following the command name the parameter is taken from the
  912. current selection.
  913.  
  914. System.RenameFiles 
  915. processes a parameter list of pairs A => B. Renames each file A to B. In the 
  916. case of a "^" following the command name the parameter is taken from the
  917. current selection.
  918.  
  919. System.DeleteFiles 
  920. deletes each file specified by the parameter list. In the case of a "^" 
  921. following the command name the parameter (a single file name) is taken
  922. from the current selection.
  923.  
  924. System.SetFont 
  925. applies the font specified by the parameter to subsequently typed characters. 
  926.  
  927. System.SetColor 
  928. applies the color specified by the parameter to subsequently typed characters. 
  929.  
  930. System.SetOffset 
  931. applies the vertical offset specified by the parameter to subsequently typed 
  932. characters. 
  933.  
  934.  
  935. The Compiler Tool Package 
  936.  
  937. This package contains the Oberon compiler. The result of compilations is shown 
  938. in the log viewer. Possible errors are listed in the log viewer together with
  939. their position in the source text. In order to locate the error within the
  940. source text, use Edit.Locate in the log viewer's title menu. The compiler
  941. tool exports a single command:
  942.  
  943. Compiler.Compile 
  944. compiles all texts specified by the parameter list. Names in the parameter 
  945. list refer to text files, the symbol * to the text in the marked viewer.
  946. In the case of a "^" fol  lowing the command name the parameter list is
  947. taken from the current selection. The following options are available:
  948. "/x" (index check off), "/v" (check integer overflow), "t" (type guards off),
  949. "/s" (allow change of symbol file), and "/d" (provide debugging information).
  950.  
  951.  
  952. The Miscellaneous Tool Package 
  953.  
  954. This package provides utilities to convert files, determine statistical data, 
  955. and demonstrate system behavior.
  956.  
  957. Miscellaneous.BootLoad FileName 
  958. downloads the named bootfile to boot sectors on disk. 
  959.  
  960. Miscellaneous.ConvertBlanks 
  961. converts all text files specified by the parameter list by replacing pairs of 
  962. leading spaces by tab characters. "^" following the command name refers to the
  963. current selection (a single file name).
  964.  
  965. Miscellaneous.ConvertTabs 
  966. converts all text files specified by the parameter list by replacing leading
  967. tab characters by pairs of spaces. "^" following the command name refers to
  968. the current selection (a single file name).
  969.  
  970. Miscellaneous.Cleanup 
  971. converts all text files specified by the parameter list into ordinary Ascii 
  972. files i.e. deletes formatting information and removes non-printable characters. "^" following the command
  973. name refers to the current selection (a single file name).
  974.  
  975. Miscellaneous.CountLines 
  976. counts the lines of all text files specified by the parameter list. "^" 
  977. following the command name refers to the current selection (a single file
  978. name).
  979.  
  980. Miscellaneous.GetObjSize 
  981. extracts code size and data size from all object files specified by the 
  982. parameter list. "^" following the command name refers to the current
  983. selection (a single file name).
  984.  
  985. Miscellaneous.Snapshot 
  986. takes a snapshot of the current state of the screen display and stores it in 
  987. the two files specified in the parameter list. The first file contains the
  988. lower half and the second file the upper half of the display.
  989.  
  990. Miscellaneous.Trap 
  991. forces a trap, thereby demonstrating the trap display mechanism. 
  992.  
  993.  
  994. The Backup Tool Package 
  995.  
  996. This package handles the transfer between main disk and diskette. It supports 
  997. diskettes conforming to a double-sided MSDOS-like format.
  998.  
  999. Backup.Format 
  1000. formats an arbitrary double-sided diskette. This command is protected. Remove 
  1001. the ! before executing this command.
  1002.  
  1003. Backup.Init 
  1004. initializes a formatted diskette to MSDOS-like Oberon format. This command is 
  1005. protected. Remove the ! before executing this command.
  1006.  
  1007.  
  1008. Backup.Directory 
  1009. displays the directory of the currently loaded diskette. 
  1010.  
  1011. Backup.DeleteFiles 
  1012. deletes all files specified by the parameter list from the currently loaded 
  1013. diskette. 
  1014.  
  1015. Backup.ReadAll 
  1016. reads all files from the currently loaded diskette. 
  1017.  
  1018. Backup.ReadFiles 
  1019. reads all files specified by the parameter list from the currently loaded 
  1020. diskette. 
  1021.  
  1022. Backup.WriteFiles 
  1023. writes all files specified by the parameter list to the currently loaded 
  1024. diskette. 
  1025.  
  1026. Backup.ConvertToMSDOS 
  1027. converts the currently loaded diskette to the official MSDOS-format P9 for 3.5 
  1028. inch Diskettes. MSDOS-restrictions for file-names are enforced (length of
  1029. filename <= 8, length of extension <= 3, upper-case characters only.
  1030.  
  1031. Backup.ConvertFormMSDOS 
  1032. converts the currently loaded diskette from the official MSDOS-format P9 for 
  1033. 3.5 inch Diskettes to the Oberon-format.
  1034.  
  1035.  
  1036. The Net Server Tool Package 
  1037.  
  1038. This package supports electronic mail and transfers of files over the local
  1039. network. It also allows a workstation to become a file server itself. It
  1040. assumes that the correct user identification has previously been installed.
  1041.  
  1042. Net.Mailbox 
  1043. opens a viewer Mailbox.Text presenting an overview of all messages currently
  1044. in the mailbox. 
  1045.  
  1046. Net.DeleteMail 
  1047. appearing in the header of viewer Mailbox.Text, deletes the message whose
  1048. entry is selected. 
  1049.  
  1050. Net.ReceiveMail 
  1051. appearing in the header of viewer Mailbox.Text, opens a viewer displaying
  1052. the message whose entry is selected.
  1053.  
  1054. Net.SendMail 
  1055. sends the message displayed in the marked viewer. The syntactical definition 
  1056. of a message is as follows:
  1057.  
  1058. message = recipient {recipient} [subject] text. 
  1059. recipient = "To:" AddressList | "cc:" AddressList. 
  1060. AddressList = address {"," address}. 
  1061. subject = "Re:" text. 
  1062.  
  1063. address is an RFC-name (@-notation) identifying an individual recipient or the
  1064. name of a list of recipients that is stored on the mail server. Instead of @,
  1065. ! and % are also accepted. No @-part is needed, if the recipient is within the
  1066. Ceres-network.
  1067.  
  1068. Net.SendFiles 
  1069. sends a sequence of files to a remote file server station. The first name in 
  1070. the parameter list identifies the desired file server and the remaining names
  1071. define the sequence of desired files. By prefixing their names files may be
  1072. sent to specific subdirectories. For example, the specification  P:F.X implies
  1073. an automatic name translation from F.X (on the master) to P.F.X (on the server).
  1074. If "^" immediately follows the server name the parameter list is taken from the
  1075. current selection.
  1076.  
  1077. Net.ReceiveFiles 
  1078. gets a sequence of files from a remote file server station. The first name in 
  1079. the parameter list identifies the desired file server and the remaining names
  1080. define the sequence of desired files. Again, prefixing and associated automatic
  1081. name-translation allows files to be received from specific subdirectories. For
  1082. example, the specification P:F.X implies an automatic name translation from
  1083. P.F.X (on the server) to F.X (on the master). If "^" immediately follows the
  1084. server name the parameter list is taken from the current selection.
  1085.  
  1086. Net.DeleteFiles 
  1087. deletes a list of files from a remote file server. The first entry in the 
  1088. parameter list is the server name. 
  1089.  
  1090. Net.SendMsg partner message 
  1091. sends a one-line-message to the specified partner. 
  1092.  
  1093. Net.GetTime 
  1094. gets the time from the server and adjusts the local clock. 
  1095.  
  1096. Net.SetPassword server "password" 
  1097. installs new password in the server. 
  1098.  
  1099. Net.StartServer 
  1100. sets the workstation in server mode, i.e. allows access from other stations in 
  1101. the net. 
  1102.  
  1103. Net.StopServer 
  1104. terminates server mode 
  1105.  
  1106. Net.Unprotect 
  1107. allows write-access from other stations. 
  1108.  
  1109. Net.WProtect 
  1110. disallows write-access from other stations (default mode). 
  1111.  
  1112.  
  1113. The ColorSystem Tool Package 
  1114.  
  1115. This package provides utilities to inspect and define parameters of the color 
  1116. display. It should only be used if a color display is physically installed.
  1117.  
  1118. ColorSystem.Init 
  1119. initializes the color display screen. 
  1120.  
  1121. ColorSystem.InitColors 
  1122. initializes the color palette. 
  1123.  
  1124. ColorSystem.ShowColors 
  1125. opens a viewer displaying the color palette. The viewer is editable. 
  1126.  
  1127. ColorSystem.LoadColors PalName 
  1128. loads the specified color palette. 
  1129.  
  1130. ColorSystem.StoreColors PalName 
  1131. stores the current palette under the name specified. 
  1132.  
  1133. ColorSystem.SetCursor x 
  1134. sets the color cursor to mode x. x = "^": arrow only, x = "+": crosshair only, 
  1135. x = "*": arrow and crosshair. 
  1136.  
  1137.  
  1138. Guide for Programmers of Commands 
  1139.  
  1140. In Oberon's modular hierarchy we recognize the following structural entities: 
  1141. The inner core, the outer core, the text system, the graphic system, the
  1142. picture system, and a collection of tools.
  1143.  
  1144.  
  1145. Oberon's module hierarchy 
  1146.  
  1147. Tool Packages 
  1148.    Net  Backup  Compiler  System      Miscellaneous    ColorSystem
  1149.                            Edit         Draw            Paint
  1150.  
  1151.                         Text System   Graphic System    Picture System
  1152.                         TextFrames    GraphicFrames     PictureFrames
  1153.                          Graphics       Pictures        MenuViewers
  1154.  
  1155.   Outer Core   Inner Core     Printer    Oberon   Texts
  1156.   Modules      Fonts          Files     FileDir   Math
  1157.   MathL  Reals Viewers  Drivers Kernel  V24  SCC   Diskette
  1158.   Input   Display
  1159.  
  1160. The responsability of the inner core comprises memory management, file
  1161. management, and program loading. The outer core additionally provides
  1162. device drivers for network ports, keyboard, mouse, and display screens.
  1163. Other parts of the outer core are viewer manager, elementary text management,
  1164. and support for (remote) printing. Module Oberon represents the main interface
  1165. between the outer core and its clients. It includes sections that are devoted
  1166. to the current system configuration, to default strategies for track allocation
  1167. and viewer placement, and to the support of command execution.
  1168.  
  1169. Module Display stands at the bottom of the display system hierarchy. The
  1170. display area is considered as a plane with x and y coordinates. It includes
  1171. both a black-and-white area and a color area. Raster operation s are used to
  1172. generate and copy rectangular areas on the display plane. Sections of the
  1173. plane can be made visible by display control procedures. The visible parts
  1174. of the display plane are structured as tracks and viewers, and they are
  1175. managed by the viewer manager Viewers.Module Oberon defines a standard
  1176. layout featuring one user track and one system track per display screen.
  1177. Finally, module MenuViewers is a high-level viewer manager for standard
  1178. viewers consisting of a title bar and a rectangular main area surrounded
  1179. by a thin frame. Both title bar and main area are so-called frames.
  1180. While the title bar is almost always a text frame (see next paragraph), the
  1181. type of the main frame depends on the kind of viewer.
  1182.  
  1183. The text system, the graphic system, and the picture system are identical
  1184. in structure. Each consists of a triple of linearly dependent modules. In
  1185. the case of texts they are called Texts, TextFrames, and Edit. Texts
  1186. defines the object type Text and exports intrinsic operations on texts.
  1187. TextFrame s defines the object type TextFrames.Frame and handles
  1188. representations of texts within sub-frames of viewers. Edit provides
  1189. additional (non-built-in) text-editing operations. 
  1190.  
  1191. Modules at the top (like Edit ) are tool packages. Typically, a tool
  1192. package merely exports a collection of commands in the form of parameterless
  1193. procedures. Tool modules make intensive use of facilities provided by lower
  1194. level modules, in particular by the viewer system, the text system, and the
  1195. central system module Oberon. It is essential that usual commands strictly
  1196. operate on texts or graphics instead of accessing keyboard or screen directly.
  1197.  
  1198. We understand this chapter as a tutorial on implementing tool packages.
  1199. First, we give a commented overview of the definitions of the most important
  1200. lower-level modules. Then, we shall exemplify their usage by some typical
  1201. excerpts from existing tools.
  1202.  
  1203.  
  1204. The Display System 
  1205.  
  1206.  
  1207. DEFINITION Display; (*display driver*) 
  1208.  
  1209.  CONST
  1210.    black   =  0;
  1211.    white   = 15;
  1212.    replace =  0;
  1213.    paint   =  1;
  1214.    invert  =  2; (*operation modes*)
  1215.  
  1216.   TYPE
  1217.   Frame = POINTER TO FrameDesc;
  1218.   FrameMsg = RECORD
  1219.              END; (*base type of messages to frames*)
  1220.  
  1221.   Pattern = LONGINT; (*pointer to pattern descriptor*)
  1222.  
  1223.   (*PatternDesc = RECORD
  1224.                     w, h: SHORTINT;
  1225.                     raster: ARRAY (w + 7) DIV 8 * h OF BYTE
  1226.                   END*)
  1227.  
  1228.   Font  = POINTER TO Bytes;
  1229.   Bytes = RECORD
  1230.           END;
  1231.  
  1232.   Handler = PROCEDURE (f: Frame, VAR msg: FrameMsg);
  1233.  
  1234.   FrameDesc = RECORD (*base type of frames*)
  1235.                 dsc, next: Frame;
  1236.                 X, Y, W, H: INTEGER;
  1237.                 handle: Handler
  1238.               END;
  1239.  
  1240.   VAR
  1241.    Unit: LONGINT; (*RasterUnit = Unit/36000 mm*)
  1242.    Left,          (*left margin of black-and-white maps*)
  1243.    ColLeft,       (*left margin of color maps*)
  1244.    Bottom,        (*Bottom of primary map*)
  1245.    UBottom,       (*Bottom of secondary map*)
  1246.    Width,         (*map width*)
  1247.    Height         (*map height*)
  1248.            : INTEGER;
  1249.  
  1250.    arrow, star, cross, downArrow, hook: Pattern;
  1251.  
  1252.   PROCEDURE Map (X: INTEGER): LONGINT; (*address of map at X*)
  1253.   PROCEDURE SetMode (X: INTEGER; s: SET); (*set mode of map at X*)
  1254.    (*black & white display: 0: display disable,
  1255.                             1: display secondary map,
  1256.                             2: inverse video*)
  1257.  
  1258.  (*color display*)
  1259.  
  1260.   PROCEDURE SetColor (col, red, green, blue: INTEGER);
  1261.   (*col < 0: overlay color*)
  1262.   PROCEDURE GetColor (col: INTEGER; VAR red, green, blue: INTEGER);
  1263.  
  1264.   PROCEDURE SetCursor(mode: SET); (*color cursor; 0: crosshair, 1: arrow*)
  1265.  
  1266.   PROCEDURE InitCC; (*initialize color crosshair to full screen*)
  1267.   PROCEDURE InitCP; (*initialize color pattern to arrow shape*)
  1268.  
  1269.   PROCEDURE DefCC (X, Y, W, H: INTEGER); (*define window for color crosshair*)
  1270.   PROCEDURE DefCP (VAR raster: ARRAY OF BYTE);
  1271.   (*define 64 x 64 raster for color pattern marker*)
  1272.   PROCEDURE DrawCX (X, Y: INTEGER); (*draw color cursor at X, Y*)
  1273.   PROCEDURE FadeCX (X, Y: INTEGER); (*fade color cursor at X, Y*)
  1274.  
  1275.  (*fonts*)
  1276.  
  1277.   PROCEDURE GetChar(f: Font;
  1278.                     ch: CHAR;
  1279.                     VAR dx, x, y, w, h: INTEGER;
  1280.                     VAR p: Pattern);
  1281.  (*get box x, y, w, h, width dx, and raster data p of character ch in font f*)
  1282.  
  1283.  (*raster operations*)
  1284.  
  1285.   PROCEDURE CopyBlock (SX, SY, W, H, DX, DY, mode: INTEGER);
  1286.   (*copy source block SX, SY, W, H to destination DX, DY using operation
  1287.     mode. A block is given by its lower left corner X, Y and its dimension
  1288.     W, H*)
  1289.  
  1290.  
  1291.   PROCEDURE CopyPattern (col: INTEGER; pat: Pattern; X, Y, mode: INTEGER);
  1292.  
  1293.    (*copy pattern p in color col to X, Y using operation mode
  1294.      col = 0: black; col = 15: white*)
  1295.  
  1296.   PROCEDURE ReplPattern (col: INTEGER;
  1297.                          pat: Pattern; X, Y, W, H, mode: INTEGER);
  1298.    (*replicate pattern p in color col into block X, Y, W, H using operation
  1299.      mode, proceeding from left to right and from bottom to top, starting
  1300.      at lower left corner*)
  1301.  
  1302.   PROCEDURE ReplConst (col: INTEGER; X, Y, W, H, mode: INTEGER);
  1303.    (*place "ones" in color col into block X, Y, W, H using operation mode*)
  1304.  
  1305.  
  1306. END Display. 
  1307.  
  1308.  
  1309. Remarks: 
  1310.  
  1311. 1. The Ceres computer features a monochrome display whose position (lower left 
  1312.    corner) is specified by the variables Left and Bottom, and whose width and
  1313.    height are given by the variables Width and Height.
  1314.    In fact, the drawing area is bigger; its y-coordinate ranges from -1248 to
  1315.    799. Two sections can be made visible by the display control procedures,
  1316.    the first being characterized by {y| -1024 <= y < -224}, and the other by
  1317.    {y| 0 <= y < 800}.
  1318.  
  1319. 2. If a color display is installed, the module's raster procedures can be used 
  1320.     to generate and copy areas on the color screen. The position of the color
  1321.     area (lower left corner) is specified by the variables ColLeft and Bottom;
  1322.     its width and height are the same as for the monochrome display.
  1323.  
  1324. 3. The postulated preconditions upon procedure parameters are not checked by 
  1325.    the module; this is left to the calling modules which are held responsible
  1326.    for robustness.
  1327.  
  1328. 4. Notice that there are the following implementation restrictions of the 
  1329.    raster operations:
  1330.  
  1331. ReplConst 
  1332.  Color display: paint mode treated as replace mode.
  1333.  
  1334. ReplPattern 
  1335.   Pattern width w ignored and taken as 32 on monochrome and as 16 on color
  1336.   display. 0 <= h < 256 on monochrome, 0 <= h <= 16 on color display.
  1337.   Color display: x and x+w should be even, otherwise 1 is subtracted.
  1338.  
  1339. CopyPattern 
  1340.   Replace mode treated like paint mode.
  1341.  
  1342.   0 < w <= 32, 0 <= h < 256.
  1343.  
  1344. CopyBlock 
  1345.   All modes treated as replace mode.
  1346.  
  1347.  
  1348. ------------------------------------------------------------------------ 
  1349.  
  1350. DEFINITION Viewers; (*viewer manager*) 
  1351.  
  1352.  IMPORT Display;
  1353.  
  1354.  CONST
  1355.  
  1356.   restore = 0; modify = 1; suspend = 2;
  1357.    (*message ids referring to the following message type*)
  1358.  
  1359.  TYPE
  1360.  
  1361.    ViewerMsg = RECORD (*message sent to viewers on viewer events*)
  1362.                  (Display.FrameMsg)
  1363.                  id: INTEGER;
  1364.                  X, Y, W, H: INTEGER;
  1365.                  state: INTEGER
  1366.                END;
  1367.  
  1368.   Viewer = POINTER TO ViewerDesc;
  1369.  
  1370.   ViewerDesc = RECORD (* viewer descriptor extends Display.FrameDesc*)
  1371.                  (Display.FrameDesc)
  1372.                  state: INTEGER
  1373.                END;
  1374.  
  1375.   (*state > 1: displayed
  1376.     state = 1: filler
  1377.     state = 0: closed
  1378.     state < 0: suspended*)
  1379.  
  1380.  VAR curW, minH: INTEGER;
  1381.  (*current width of logical display, minimum viewer height*)
  1382.  
  1383.  PROCEDURE InitTrack (W, H: INTEGER; Filler: Viewer);
  1384.   (*append to current logical display and init track of width W and height H
  1385.     and install Filler*)
  1386.  
  1387.  PROCEDURE OpenTrack (X, W: INTEGER; Filler: Viewer);
  1388.   (*open new track overlaying span of [X, X + W[*)
  1389.  
  1390.  PROCEDURE CloseTrack (X: INTEGER);
  1391.   (*close track at X and restore overlaid tracks*)
  1392.  
  1393.  PROCEDURE Locate (X, H: INTEGER; VAR fil, bot, alt, max: Display.Frame);
  1394.   (*in the track at X locate the following viewers:
  1395.    filler fil,
  1396.    bottom viewer bot,
  1397.    an alternative viewer alt of height >= H,
  1398.    viewer max of maximum height*)
  1399.  
  1400.  PROCEDURE Open (V: Viewer; X, Y: INTEGER);
  1401.   (*open new viewer V with top at Y in track at X*)
  1402.  
  1403.  PROCEDURE Change (V: Viewer; Y: INTEGER);
  1404.   (*expand or shrink viewer V to new top Y*)
  1405.  
  1406.  PROCEDURE Close (V: Viewer);
  1407.   (*remove viewer V from the display*)
  1408.  
  1409.  PROCEDURE Recall (VAR V: Viewer);
  1410.   (*recall most recently closed viewer*)
  1411.  
  1412.  
  1413.  PROCEDURE This (X, Y: INTEGER): Viewer;
  1414.   (*return viewer at X, Y*)
  1415.  
  1416.  PROCEDURE Next (V: Viewer): Viewer;
  1417.   (*return next upper neighbour of V*)
  1418.  
  1419.  PROCEDURE Broadcast (VAR M: Display.FrameMsg);
  1420.   (*send message M to all visible viewers*)
  1421.  
  1422. END Viewers. 
  1423.  
  1424. -------------------------------------------------------------------------- 
  1425.  
  1426. DEFINITION MenuViewers; 
  1427.  
  1428.  IMPORT Display, Viewers;
  1429.  
  1430.  CONST extend = 0; reduce = 1; (*message ids*)
  1431.  
  1432.  TYPE Viewer = POINTER TO ViewerDesc;
  1433.  
  1434.  ViewerDesc = RECORD (Viewers.ViewerDesc)
  1435.                 menuH: INTEGER (*height of menu frame*)
  1436.               END;
  1437.  
  1438.   ModifyMsg = RECORD (Display.FrameMsg)
  1439.                 id: INTEGER; (*extend or reduce*)
  1440.                 dY, Y, H: INTEGER (*translation vector dY; new Y and H*)
  1441.               END;
  1442.  
  1443.  VAR Ancestor: Viewer; (*current menu viewer*)
  1444.  
  1445.  PROCEDURE Handle (V: Display.Frame; VAR M: Display.FrameMsg);
  1446.    (*standard handler for menu viewers*)
  1447.  
  1448.  PROCEDURE New (Menu, Main: Display.Frame; menuH, X, Y: INTEGER): Viewer;
  1449.     (*create and open at X, Y new menu viewer containing frames Menu and
  1450. Main*) 
  1451.  
  1452. END MenuViewers. 
  1453.  
  1454.  
  1455. Remark: 
  1456.  
  1457. Messages to menu viewers not affexting size and position are passed on to 
  1458. their subframes. The ancestor viewer is made available to the subframe
  1459. handlers via the variable Ancestor. MenuViewers also creates new messages
  1460. of type ModifyMsg requesting subframes to change size or vertical position
  1461. (or both). dY represents a vertical translation vector, and Y and H specify
  1462. the new position and height respectively.
  1463.  
  1464.  
  1465. -------------------------------------------------------------------------- 
  1466.  
  1467.  
  1468. The Text System 
  1469.  
  1470. DEFINITION Fonts; (*font loader*) 
  1471.  
  1472.  IMPORT Display;
  1473.  
  1474.  
  1475.  TYPE
  1476.  
  1477.    Name = ARRAY 32 OF CHAR;
  1478.  
  1479.    Font = POINTER TO FontDesc;
  1480.  
  1481.    FontDesc = RECORD
  1482.                 name: Name; (*file name*)
  1483.                 height, minX, maxX, minY, maxY: INTEGER;
  1484.                 (*characteristic data*)
  1485.                 raster: Display.Font (*raster data*)
  1486.               END;
  1487.  
  1488.    (*height = minimum distance between text lines,
  1489.    minX, maxX, minY, maxY are minima and maxima of X and Y,
  1490.    if all character boxes of the font are placed at the origin 0, 0*)
  1491.  
  1492.  VAR Default: Font; (*the default font*)
  1493.  
  1494.    PROCEDURE This (name: ARRAY OF CHAR): Font;
  1495.    (*font with name given*)
  1496.  
  1497. END Fonts. 
  1498.  
  1499. -------------------------------------------------------------------------- 
  1500.  
  1501. DEFINITION Texts; (*text manager*) 
  1502.  
  1503.  IMPORT Files, Fonts;
  1504.  
  1505.  CONST
  1506.  
  1507.   (*symbol classes, see def. of type Scanner*)
  1508.  
  1509.   Inval    = 0;  (*invalid symbol*)
  1510.   Name     = 1;  (*name s (length len)*)
  1511.   String   = 2;  (*literal string s (length len)*)
  1512.   Int      = 3;  (*integer i (decimal or hexadecimal)*)
  1513.   Real     = 4;  (*real number x*)
  1514.   LongReal = 5;  (*long real number y*)
  1515.   Char     = 6;  (*special character c*)
  1516.  
  1517.   replace = 0;
  1518.   insert  = 1;
  1519.   delete  = 2;   (*op-codes*)
  1520.  
  1521.  
  1522.  TYPE
  1523.  
  1524.   Text = POINTER TO TextDesc;
  1525.  
  1526.   Notifier = PROCEDURE (T: Text; op: INTEGER; beg, end: LONGINT);
  1527.  
  1528.   TextDesc = RECORD
  1529.                len: LONGINT; (*text length*)
  1530.                notify: Notifier (*of editing operations*)
  1531.              END;
  1532.  
  1533.   Reader = RECORD
  1534.              (Files.Rider)
  1535.              eot: BOOLEAN;
  1536.              fnt: Fonts.Font; (*font of current character*)
  1537.              col: SHORTINT; (*color of current character*)
  1538.              voff: SHORTINT (*vertical offset*)
  1539.            END;
  1540.  
  1541.   Scanner = RECORD
  1542.               (Reader)
  1543.               nextCh: CHAR;
  1544.               line: INTEGER;
  1545.               class: INTEGER;
  1546.               i: LONGINT;
  1547.               x: REAL;
  1548.               y: LONGREAL;
  1549.               c: CHAR;
  1550.               len: SHORTINT;
  1551.               s: ARRAY 32 OF CHAR
  1552.             END;
  1553.  
  1554.    (*used to convert a text into a stream of symbols.
  1555.    Symbol classes are defined under CONST*)
  1556.  
  1557.   Buffer = POINTER TO BufDesc;
  1558.  
  1559.   BufDesc = RECORD
  1560.               len: LONGINT (*buffer length*)
  1561.             END;
  1562.  
  1563.   (*used to write a stream of textual data in a buffer*)
  1564.  
  1565.   (*used to store a stretch of a text*)
  1566.  
  1567.   Writer = RECORD
  1568.              (Files.Rider)
  1569.              buf: Buffer; (*associated buffer*)
  1570.              fnt: Fonts.Font; (*current font*)
  1571.              col: SHORTINT; (*color of current character*)
  1572.              voff: SHORTINT (*vertical offset*)
  1573.            END;
  1574.  
  1575.  PROCEDURE Load (T: Text; f: Files.File; pos: LONGINT; VAR len: LONGINT);
  1576.   (*load text block from file f at position pos to text T*)
  1577.  
  1578.  PROCEDURE Open (T: Text; name: ARRAY OF CHAR);
  1579.   (*open text T from disk file specified by name; open new text if name = ""*)
  1580.  
  1581.  PROCEDURE OpenBuf (B: Buffer);
  1582.   (*open new text buffer B*)
  1583.  
  1584.  PROCEDURE OpenReader (VAR R: Reader; T: Text; pos: LONGINT);
  1585.   (*open text reader R and set it up at position pos in text T*)
  1586.  
  1587.  PROCEDURE Read (VAR R: Reader; VAR ch: CHAR);
  1588.   (*read next character in ch*)
  1589.  
  1590.  PROCEDURE Pos (VAR R: Reader): LONGINT;
  1591.   (*return reader's position within its text*)
  1592.  
  1593.  PROCEDURE Store (T: Text; f: Files.File; pos: LONGINT; VAR len: LONGINT);
  1594.   (*store text T on disk file f at position pos*)
  1595.  
  1596.  PROCEDURE Save (T: Text; beg, end: LONGINT; B: Buffer);
  1597.   (*append stretch [beg, end[ of text T to buffer B*)
  1598.  
  1599.  PROCEDURE Copy (SB, DB: Buffer);
  1600.   (*append copy of source buffer SB to destination buffer DB*)
  1601.  
  1602.  PROCEDURE ChangeLooks (T: Text;
  1603.                         beg, end: LONGINT;
  1604.                         sel: SET;
  1605.                         fnt: Fonts.Font;
  1606.                         col, voff:SHORTINT);
  1607.   (*change character attributes within stretch [beg, end[ of text T. sel
  1608.     selects attributes to be changed. 0, 1, 2 IN sel = fnt, col, voff selected*)
  1609.  
  1610.  PROCEDURE Insert (T: Text; pos: LONGINT; B: Buffer);
  1611.   (*insert buffer B in text T at position pos*)
  1612.  
  1613.  PROCEDURE Append (T: Text; B: Buffer);
  1614.   (*append buffer B to text T*)
  1615.  
  1616.  PROCEDURE Delete (T: Text; beg, end: LONGINT);
  1617.   (*delete stretch [beg, end[ of text T*)
  1618.  
  1619.  PROCEDURE Recall (VAR B: Buffer);
  1620.   (*recall previously deleted text*)
  1621.  
  1622.  PROCEDURE OpenScanner (VAR S: Scanner; T: Text; pos: LONGINT);
  1623.   (*open text scanner S and set it up at position pos in text T*)
  1624.  
  1625.  PROCEDURE Scan (VAR S: Scanner);
  1626.   (*read next symbol*)
  1627.  
  1628.  PROCEDURE OpenWriter (VAR W: Writer);
  1629.   (*open new writer W*)
  1630.  
  1631.  PROCEDURE SetFont (VAR W: Writer; fnt: Fonts.Font);
  1632.   (*set writer W to font fnt*)
  1633.  
  1634.  PROCEDURE SetColor (VAR W: Writer; col: SHORTINT);
  1635.   (*set writer W to color col*)
  1636.  
  1637.  PROCEDURE SetOffset (VAR W: Writer; voff: SHORTINT);
  1638.   (*set writer W to vertical offset voff*)
  1639.  
  1640.  PROCEDURE Write (VAR W: Writer; ch: CHAR);
  1641.   (*write character ch to W's buffer*)
  1642.  
  1643.  PROCEDURE WriteLn (VAR W: Writer);
  1644.   (*write end-of-line to W's buffer*)
  1645.  
  1646.  PROCEDURE WriteInt (VAR W: Writer; x, n: LONGINT);
  1647.   (*write integer x to W's buffer. Right adjust to n positions*)
  1648.  
  1649.  PROCEDURE W
  1650.  riteHex (VAR W: Writer; x: LONGINT); 
  1651.   (*write integer x to W's buffer in hexadecimal form.
  1652.  
  1653.  PROCEDURE WriteString (VAR W: Writer; s: ARRAY OF CHAR);
  1654.   (*write string s to W's buffer*)
  1655.  
  1656.  PROCEDURE WriteReal (VAR W: Writer; x: REAL; n: INTEGER);
  1657.   (*write real number x to W's buffer. Use n positions*)
  1658.  
  1659.  PROCEDURE WriteRealFix (VAR W: Writer; x: REAL; n, k: INTEGER);
  1660.   (*write real number x to W's buffer in fixed-point form,
  1661.    using k positions for decimal fractions and n positions in total*)
  1662.  
  1663.  
  1664.  PROCEDURE WriteRealHex (VAR W: Writer; x: REAL);
  1665.   (*write real number x to W's buffer in hexadecimal form*)
  1666.  
  1667.  PROCEDURE WriteLongReal (VAR W: Writer; x: LONGREAL; n: INTEGER);
  1668.   (*write long real number x to W's buffer. Use n positions*)
  1669.  
  1670.  PROCEDURE WriteLongRealHex (VAR W: Writer; x: LONGREAL);
  1671.   (*write long real number x to W's buffer in hexadecimal form*)
  1672.  
  1673. END Texts. 
  1674.  
  1675.  
  1676. Remark: 
  1677.  
  1678. Open does not create a text object nor does it install a notifier procedure. 
  1679. Both actions are left to the calling modules. Typically, a calling module
  1680. first creates a text object (or an extension of it) by using NEW, and then
  1681. installs a notifier procedure. The main purpose of notifier procedures is
  1682. requesting the display to re-establish consistency after a change in a text
  1683. has occurred.
  1684.  
  1685. -------------------------------------------------------------------------- 
  1686.  
  1687. DEFINITION TextFrames; (*text display*) 
  1688.  
  1689.  IMPORT Display, Texts;
  1690.  
  1691.  TYPE
  1692.  
  1693.   Location = RECORD
  1694.                org, pos: LONGINT; (*line origin, position*)
  1695.                dx, x, y: INTEGER (*width and position of located character*)
  1696.              END;
  1697.  
  1698.   Frame = POINTER TO FrameDesc;
  1699.  
  1700.   FrameDesc = RECORD
  1701.                 (Display.FrameDesc)
  1702.                 text: Texts.Text; (*displayed text*)
  1703.                 org: LONGINT; (*position in text of first displayed character*)
  1704.                 col: INTEGER; (*background color*)
  1705.                 lsp, asr, dsr: INTEGER; (*line spacing, ascender, descender*)
  1706.                 left, right, top, bot: INTEGER; (*margins*)
  1707.                 markH: INTEGER; (*margin width, position of mark*)
  1708.                 time: LONGINT; (*time of latest selection*)
  1709.                 mark, car, sel: INTEGER; (*state of mark, caret, selection*)
  1710.                 carloc: Location; (*caret location*)
  1711.                 selbeg, selend: Location (*locations of begin and end of selection*)
  1712.               END;
  1713.  
  1714.   (*mark < 0: arrow mark
  1715.     mark = 0: no mark
  1716.     mark > 0: position mark
  1717.      car = 0: caret not set
  1718.      car > 0: caret set
  1719.      sel = 0: no selection active
  1720.      sel > 0: selection active*)
  1721.  
  1722.    UpdateMsg = RECORD
  1723.                  (Display.FrameMsg)
  1724.                  id: INTEGER;
  1725.                  text: Texts.Text;
  1726.                  beg, end: LONGINT
  1727.                END;
  1728.  
  1729.   VAR menuH, barW, left, right, top, bot, asr, dsr, lsp: INTEGER;
  1730.   (*standard sizes*)
  1731.  
  1732.    PROCEDURE Restore (F: Frame);
  1733.     (restore frame F*)
  1734.  
  1735.    PROCEDURE Suspend(F: Frame);
  1736.     (*suspend frame F*)
  1737.  
  1738.    PROCEDURE Extend (F: Frame; newY: INTEGER);
  1739.    (*extend frame F to bottom newY*)
  1740.  
  1741.   PROCEDURE Reduce (F: Frame; newY: INTEGER);
  1742.    (*reduce frame F to bottom newY*)
  1743.  
  1744.   PROCEDURE Mark (F: Frame; mark: INTEGER);
  1745.    (*mark frame F as specified by mark*)
  1746.  
  1747.   PROCEDURE Show (F: Frame; pos: LONGINT);
  1748.    (*show text part containing position pos in frame F*)
  1749.  
  1750.   PROCEDURE Pos (F: Frame; X, Y: INTEGER): LONGINT;
  1751.    (*convert coordinates X, Y to text position*)
  1752.  
  1753.   PROCEDURE SetCaret (F: Frame; pos: LONGINT);
  1754.    (*set caret in frame F at position pos*)
  1755.  
  1756.   PROCEDURE TrackCaret (F: Frame; X, Y: INTEGER; VAR keysum: SET);
  1757.    (*track caret in frame F, starting from X, Y, and return mouse-keys
  1758.      pressed*)
  1759.  
  1760.   PROCEDURE RemoveCaret (F: Frame);
  1761.    (*remove caret from frame F*)
  1762.  
  1763.   PROCEDURE SetSelection (F: Frame; beg, end: LONGINT);
  1764.    (*select text stretch [beg, end[ in F*)
  1765.  
  1766.   PROCEDURE TrackSelection (F: Frame; X, Y: INTEGER; VAR keysum: SET);
  1767.    (*track selection in frame F, starting from X, Y, and return mouse-keys
  1768.      pressed*)
  1769.  
  1770.   PROCEDURE RemoveSelection (F: Frame);
  1771.    (*remove selection from frame F*)
  1772.  
  1773.   PROCEDURE TrackLine (F: Frame;
  1774.                        X, Y: INTEGER;
  1775.                        VAR org: LONGINT;
  1776.                        VAR keysum: SET);
  1777.    (*track text line in frame F, starting from X, Y, and return line-origin
  1778.      and mouse-keys pressed*)
  1779.  
  1780.   PROCEDURE TrackWord (F: Frame;
  1781.                        X, Y: INTEGER;
  1782.                        VAR pos: LONGINT;
  1783.                        VAR keysums: SET);
  1784.    (*track text word in frame F, starting from X, Y,
  1785.      and return starting position and mouse-keys pressed*)
  1786.  
  1787.   PROCEDURE Replace (F: Frame; beg, end: LONGINT);
  1788.    (*text stretch [beg, end[ was replaced; update frame F*)
  1789.  
  1790.   PROCEDURE Insert (F: Frame; beg, end: LONGINT);
  1791.    (*text stretch [beg, end[ was inserted; update frame F*)
  1792.  
  1793.   PROCEDURE Delete (F: Frame; beg, end: LONGINT);
  1794.    (*text stretch [beg, end[ was deleted; update frame F*)
  1795.  
  1796.  
  1797.   (*---------------- message handling ----------------*)
  1798.  
  1799.   PROCEDURE NotifyDisplay (T: Texts.Text; op: INTEGER; beg, end: LONGINT);
  1800.  
  1801.    (*notify display manager of text status change*)
  1802.  
  1803.   PROCEDURE Call* (F: Frame; pos: LONGINT; new: BOOLEAN);
  1804.    (*call command specified at pos in frame F. new forces loading of newest
  1805.      version*)
  1806.  
  1807.   PROCEDURE Write* (F: Frame;
  1808.                     ch: CHAR; fnt:
  1809.                     Fonts.Font;
  1810.                     col, voff: SHORTINT);
  1811.    (*write character ch with given attributes at caret position*)
  1812.  
  1813.   PROCEDURE Defocus* (F: Frame); (F: Frame; ch: CHAR; fnt: Fonts.Font; col,voff: SHORTINT);
  1814.    (*remove caret*)
  1815.  
  1816.   PROCEDURE Neutralize* (F: Frame);
  1817.    (*remove marks*)
  1818.  
  1819.   PROCEDURE Modify* (F: Frame; id, dY, Y, H: INTEGER);
  1820.    (*vertically translate and extend or reduce frame F. id indicates type
  1821.      (extension or reduction), dy is a translation vector, and Y, H specify
  1822.      new location and height respectively*)
  1823.  
  1824.   PROCEDURE Open* (F: Frame; H: Display.Handler; T: Texts.Text; org: LONGINT;
  1825.                    col, left, right, top, bot, asr, dsr, lsp: INTEGER);
  1826.    (*open new text frame F displaying text T starting from position org,
  1827.      with background color col, margins left, right, top, bot, and line
  1828.      geometry asr, dsr, lsp = ascender, descender line spacing.
  1829.       Install notifier H*)
  1830.  
  1831.   PROCEDURE Copy* (F: Frame; VAR F1: Frame);
  1832.    (*generate copy F1 of frame F. Initialize to empty frame*)
  1833.  
  1834.   PROCEDURE CopyOver* (F: Frame; text: Texts.Text; beg, end: LONGINT);
  1835.    (*copy over text stretch [beg, end[ to caret position in frame F*)
  1836.  
  1837.   PROCEDURE GetSelection* (F: Frame;
  1838.                            VAR text: Texts.Text;
  1839.                            VAR beg, end, time: LONGINT);
  1840.    (*get current text selection in frame F (if any)*)
  1841.  
  1842.   PROCEDURE Update* (F: Frame; VAR M: UpdateMsg);
  1843.    (*update display after editing operation*)
  1844.  
  1845.   PROCEDURE Edit* (F: Frame; X, Y: INTEGER; Keys: SET);
  1846.    (*track mouse and interpret editing commands*)
  1847.  
  1848.   PROCEDURE Handle* (F: Display.Frame; VAR M: Display.FrameMsg);
  1849.    (*standard handler for text frames*)
  1850.  
  1851.   PROCEDURE Text* (name: ARRAY OF CHAR): Texts.Text;
  1852.    (*create new displayed text from named file. Empty file name means empty
  1853.      text*)
  1854.  
  1855.   PROCEDURE NewMenu* (name, commands: ARRAY OF CHAR): Frame;
  1856.    (*create new menu frame containing listed commands*)
  1857.  
  1858.   PROCEDURE NewText* (text: Texts.Text; pos: LONGINT): Frame;
  1859.    (*create new standard text frame*)
  1860.  
  1861. END TextFrames. 
  1862.  
  1863. -------------------------------------------------------------------------- 
  1864.  
  1865.  
  1866. The Oberon Core 
  1867.  
  1868. DEFINITION Math; (*math library for reals*) 
  1869.  
  1870.  CONST pi = 3.14159265; e = 2.71828182;
  1871.  
  1872.  PROCEDURE sqrt(x: REAL): REAL;
  1873.  PROCEDURE exp(x: REAL): REAL;
  1874.  PROCEDURE ln(x: REAL): REAL;
  1875.  PROCEDURE sin(x: REAL): REAL;
  1876.  PROCEDURE cos(x: REAL): REAL;
  1877.  PROCEDURE arctan(x: REAL): REAL;
  1878.  
  1879. END Math. 
  1880.  
  1881. -------------------------------------------------------------------------- 
  1882.  
  1883. DEFINITION MathL; (*math library for longreals*) 
  1884.  
  1885.   CONST pi = 3.141592653589793D0;
  1886.          e = 2.718281828459045D0;
  1887.  
  1888.  
  1889.  PROCEDURE sqrt(x: LONGREAL): LONGREAL;
  1890.  PROCEDURE exp(x: LONGREAL): LONGREAL;
  1891.  PROCEDURE ln(x: LONGREAL): LONGREAL;
  1892.  PROCEDURE sin(x: LONGREAL): LONGREAL;
  1893.  PROCEDURE cos(x: LONGREAL): LONGREAL;
  1894.  PROCEDURE arctan(x: LONGREAL): LONGREAL;
  1895.  
  1896. END MathL. 
  1897.  
  1898. -------------------------------------------------------------------------- 
  1899.  
  1900. DEFINITION Files; (*file manager*) 
  1901.  
  1902.  TYPE
  1903.     Handle = RECORD END ;
  1904.     File  = POINTER TO Handle;
  1905.  
  1906.    (*A file is a sequence of bytes, accessed via (a pointer to) a handle.
  1907.      Files are stored on disk and may be referenced through a name entered
  1908.      in the file directory*)
  1909.  
  1910.     Rider = RECORD
  1911.               res: INTEGER;
  1912.               eof: BOOLEAN
  1913.             END;
  1914.  
  1915.   (*Elements of files are accessed through a rider, which has a position that
  1916.     is advanced when reading or writing data. The position is an integer
  1917.     between 0 and the length of the file to which the rider is attached.
  1918.     The fields eof and res serve as result parameters of file procedures.*)
  1919.  
  1920.  PROCEDURE Old(name: ARRAY OF CHAR): File;
  1921.   (*the file with the given name. NIL if the name is not in the directory*)
  1922.  
  1923.  PROCEDURE New(name: ARRAY OF CHAR): File;
  1924.   (*a new file with given name*)
  1925.  
  1926.  PROCEDURE Register(f: File);
  1927.   (*Close file f and register it under its name in the directory.
  1928.    If the name exists already, the corresponding old file is unregistered*)
  1929.  
  1930.  
  1931.  PROCEDURE Close(f: File);
  1932.  
  1933.  PROCEDURE Purge(f: File);
  1934.  
  1935.  PROCEDURE Length(f: File): LONGINT; (*the number of bytes in the file*)
  1936.  
  1937.  PROCEDURE Set(VAR r: Rider; f: File; pos: LONGINT);
  1938.   (*Associate rider r with file f at position pos. r.eof := FALSE*)
  1939.  
  1940.  PROCEDURE Read(VAR r: Rider; VAR x: BYTE);
  1941.   (*read byte and advance rider by one position. If at end, r.eof := TRUE and
  1942.     x := 0X*)
  1943.  
  1944.  PROCEDURE ReadBytes(VAR r: Rider; VAR x: ARRAY OF BYTE; n: INTEGER);
  1945.   (*read n bytes and advance rider by n positions.
  1946.    If at end, r.eof := TRUE and r.res := no. of bytes requested but not
  1947.    read.*)
  1948.  
  1949.  PROCEDURE Write(VAR r: Rider; x: BYTE);
  1950.   (*write byte and advance rider by one position*)
  1951.  
  1952.  PROCEDURE WriteBytes(VAR r: Rider; VAR x: ARRAY OF BYTE; n: INTEGER);
  1953.   (*write n bytes and advance rider by n positions*)
  1954.  
  1955.  PROCEDURE Pos(VAR r: Rider): LONGINT;
  1956.  
  1957.  PROCEDURE Base(VAR r: Rider): File;
  1958.  
  1959.  PROCEDURE Rename(old, new: ARRAY OF CHAR; VAR res: INTEGER);
  1960.   (*res = 0: renamed; res = 1: new name existed already and now denotes the
  1961.    renamed file; res = 2: old name not in directory; res = 3: name is illegal;
  1962.    res = 4: name is too long *)
  1963.  
  1964.  PROCEDURE Delete(name: ARRAY OF CHAR; VAR res: INTEGER);
  1965.   (*res = 0: deleted; res = 2: name not in directory;
  1966.     res = 3: name is illegal; res = 4: name is too long *)
  1967.  
  1968. END Files. 
  1969.  
  1970. -------------------------------------------------------------------------- 
  1971.  
  1972. DEFINITION Diskette; (*diskette manager*) 
  1973.  
  1974.   TYPE EntryHandler = PROCEDURE (name: ARRAY OF CHAR;
  1975.                                  date, time, size: LONGINT);
  1976.  
  1977.  VAR res: INTEGER; (*result of file-oriented operation, error occurred =
  1978.                      (res #0)*)
  1979.     err: SHORTINT; sect: LONGINT; busy: BOOLEAN; (*state of device driver*)
  1980.  
  1981.  
  1982.  (*device driver*)
  1983.  PROCEDURE Reset;
  1984.  PROCEDURE GetSector (sec: INTEGER; VAR buf: ARRAY OF BYTE; off: INTEGER);
  1985.  PROCEDURE PutSector (sec: INTEGER; VAR buf: ARRAY OF BYTE; off: INTEGER);
  1986.  PROCEDURE Format;
  1987.  
  1988.  (*directory handler*)
  1989.  PROCEDURE InitDir (format: CHAR); (*format for future extension*)
  1990.  PROCEDURE ReadDir;
  1991.  PROCEDURE WriteDir;
  1992.  PROCEDURE GetData (VAR date, time, nofFiles, nofClusters: INTEGER); (*get volume data*)
  1993.  PROCEDURE Enumerate (proc: EntryHandler);
  1994.  
  1995.  (*file handler*)
  1996.  PROCEDURE ReadAll;
  1997.  PROCEDURE ReadFile (name: ARRAY OF CHAR);
  1998.  
  1999.  PROCEDURE WriteFile (name: ARRAY OF CHAR);
  2000.  PROCEDURE DeleteFile (name: ARRAY OF CHAR);
  2001.  
  2002. END Diskette. 
  2003.  
  2004. -------------------------------------------------------------------------- 
  2005.  
  2006. DEFINITION Input; (*keyboard and mouse driver*)
  2007.  
  2008.  PROCEDURE Available(): INTEGER;
  2009.   (*the number of characters available from the keyboard*)
  2010.  
  2011.  PROCEDURE Read (VAR ch: CHAR);
  2012.   (*next character from keyboard*)
  2013.  
  2014.  PROCEDURE Mouse (VAR keys: SET; VAR x, y: INTEGER);
  2015.   (*current coordinates and key setting of mouse.
  2016.    0 IN keys = right key pressed
  2017.    1 IN keys = middle key pressed
  2018.    2 IN keys = left key pressed*)
  2019.  
  2020.  PROCEDURE SetMouseLimits (w, h: INTEGER);
  2021.   (* define width and height of rectangle in which mouse moves*)
  2022.  
  2023.  PROCEDURE Time(): LONGINT;
  2024.   (* current system time in units of 1/300 sec*)
  2025.  
  2026. END Input. 
  2027.  
  2028. -------------------------------------------------------------------------- 
  2029.  
  2030. DEFINITION SCC; (*SCC driver*) 
  2031.  
  2032.  (*Serial Communications Controller driver module (Zilog Z8530)
  2033.   Data are transmitted in blocks. Each block contains two parts: header and
  2034.   data *)
  2035.  
  2036.  TYPE Header = RECORD
  2037.                  valid: BOOLEAN;
  2038.                  dadr, sadr, typ: SHORTINT;
  2039.                  len: INTEGER; (*of data following header*)
  2040.                  destLink, srcLink: INTEGER (*link numbers*)
  2041.               END;
  2042.  
  2043.  (*dadr is the receiver's machine number, len is the length (number of bytes)
  2044.    of the data part. typ, destLink, and srcLink are not interpreted by SCC*)
  2045.  
  2046.  PROCEDURE Start(filter: BOOLEAN);
  2047.   (*initialise the SCC*)
  2048.  
  2049.  PROCEDURE Send(VAR head, buf: ARRAY OF BYTE);
  2050.   (*send buf[0]... buf[head.len-1] to head.adr*)
  2051.  
  2052.  PROCEDURE Available(): INTEGER;
  2053.   (*number of bytes available from receiver buffer. Buffer contains stream
  2054.     of received bytes, including headers and data parts*)
  2055.  
  2056.  PROCEDURE ReceiveHead(VAR head: ARRAY OF BYTE);
  2057.   (*read a header from the receiver buffer*)
  2058.  
  2059.  PROCEDURE Receive(VAR x: BYTE);
  2060.   (*read a byte from the receiver buffer*)
  2061.  
  2062.  
  2063.  PROCEDURE Skip(m: INTEGER);
  2064.   (*skip m bytes in the receiver buffer*)
  2065.  
  2066.  PROCEDURE Stop; (*turn SCC off*)
  2067.  
  2068. END SCC. 
  2069.  
  2070. -------------------------------------------------------------------------- 
  2071.  
  2072. DEFINITION V24; (*V24 driver*) 
  2073.  
  2074. (*interrupt-driven UART channel B*) 
  2075.  
  2076. PROCEDURE Start(CSR, MR2: CHAR); 
  2077. (* Clock Select Register: 
  2078.    66X: 1200 bps
  2079.    88X: 2400 bps
  2080.   0BBX: 9600 bps
  2081.  
  2082. Mode Register 2: 
  2083.   7X: 1 stop bit
  2084.  0FX: 2 stop bits *)
  2085.  
  2086. PROCEDURE SetOP(s: SET); (*output port*) 
  2087. PROCEDURE ClearOP(s: SET); 
  2088. (* 0: DTR, 1: RTS *)
  2089.  
  2090. PROCEDURE IP(n: INTEGER): BOOLEAN; (*input port*)
  2091.  
  2092. PROCEDURE SR(n: INTEGER): BOOLEAN; 
  2093. (*Status Register. 0: Rx rdy, 2: Tx rdy, 4: overrun*) 
  2094.  
  2095. PROCEDURE Available(): INTEGER; 
  2096. PROCEDURE Receive(VAR x: BYTE); 
  2097. PROCEDURE Send(x: BYTE); 
  2098.  
  2099. PROCEDURE Break; 
  2100. PROCEDURE Stop; 
  2101.  
  2102. END V24. 
  2103.  
  2104. -------------------------------------------------------------------------- 
  2105.  
  2106. DEFINITION Printer; (*printer interface*) 
  2107.  
  2108.   VAR res: INTEGER; (*result*)
  2109.  
  2110.   PROCEDURE Open(VAR name, user: ARRAY OF CHAR; password: LONGINT);
  2111. (*res = 0: opened, 1: no printer, 2: no link, 3: bad response, 4: no 
  2112.   permission*)
  2113.  
  2114.   PROCEDURE Font (fno: SHORTINT; VAR name: ARRAY OF CHAR); (*install font*)
  2115.   PROCEDURE String (x, y: INTEGER; VAR s: ARRAY OF CHAR; fno: SHORTINT);
  2116.   (*place string*)
  2117.   PROCEDURE ContString (VAR s: ARRAY OF CHAR; fno: SHORTINT); (*place continuation string*)
  2118.   PROCEDURE Line (x, y, w, h: INTEGER); (*place horizontal or vertical line*)
  2119.   PROCEDURE XLine (x, y, dx, dy: INTEGER); (*place line of general direction*)
  2120.   PROCEDURE Circle (x, y, a, b: INTEGER); (*place circle or ellipsis*)
  2121.   PROCEDURE Shade (x, y, w, h, col: INTEGER); (*shade area*)
  2122.   PROCEDURE Picture (x, y, w, h, mode: INTEGER; adr: LONGINT); (*place picture*)
  2123.   PROCEDURE Page(nofcopies: INTEGER); (*print current page*)
  2124.  
  2125.   PROCEDURE Close; (*close connection*)
  2126.  
  2127. END Printer. 
  2128.  
  2129. -------------------------------------------------------------------------- 
  2130.  
  2131. DEFINITION Oberon; (*system manager*) 
  2132.  
  2133.  IMPORT Display, Viewers, Texts;
  2134.  
  2135.  CONST
  2136.  
  2137.   consume = 0; track = 1; (*ids for input messages*)
  2138.   defocus = 0; neutralize = 1; mark = 2; (*ids for control messages*)
  2139.  
  2140.  TYPE
  2141.  
  2142.   Painter = PROCEDURE (x, y: INTEGER);
  2143.   Marker = RECORD
  2144.              Fade, Draw: Painter
  2145.            END;
  2146.  
  2147.   Cursor = RECORD
  2148.              on: BOOLEAN;
  2149.              m: Marker;
  2150.              X, Y: INTEGER
  2151.            END;
  2152.  
  2153.   ParList = POINTER TO ParRec;
  2154.  
  2155.   ParRec = RECORD
  2156.              vwr: Viewers.Viewer; (*caller's viewer*)
  2157.              frame: Display.Frame; (*caller's sub-frame*)
  2158.              text: Texts.Text; (*parameter list*)
  2159.              pos: LONGINT (*starting position of parameter list*)
  2160.            END;
  2161.  
  2162.   InputMsg = RECORD
  2163.                (Display.FrameMsg)
  2164.                id: INTEGER; (*message id*)
  2165.                modes, keys: SET; (*current modes and mouse keys*)
  2166.                X, Y: INTEGER; (*current location of the mouse*)
  2167.               ch: CHAR (*current char*)
  2168.             END;
  2169.  
  2170.   ControlMsg = RECORD
  2171.                  (Display.FrameMsg)
  2172.                  id: INTEGER; (*message id*)
  2173.                  X, Y: INTEGER (*current location of the mous*)
  2174.                END;
  2175.  
  2176.   SelectionMsg = RECORD
  2177.                    (Display.FrameMsg)
  2178.                    time: LONGINT;
  2179.                    text: Texts.Text;
  2180.                    beg, end: LONGINT
  2181.                  END;
  2182.  
  2183.    CopyOverMsg = RECORD
  2184.                    (Display.FrameMsg)
  2185.                    text: Texts.Text;
  2186.                    beg, end: LONGINT
  2187.                  END;
  2188.  
  2189.   CopyMsg = RECORD
  2190.               (Display.FrameMsg)
  2191.                F: Display.Frame
  2192.             END;
  2193.  
  2194.   Task = POINTER TO TaskDesc; (*installable task*)
  2195.  
  2196.   Handler = PROCEDURE;
  2197.  
  2198.   TaskDesc = RECORD
  2199.                safe: BOOLEAN; (*safe tasks are not removed after trap*)
  2200.                handle: Handler
  2201.              END;
  2202.  
  2203.  VAR
  2204.  
  2205.  (*configuration*)
  2206.  
  2207.   FocusViewer: Viewers.Viewer; (*current focus viewer*)
  2208.   Log: Texts.Text; (*system log text*)
  2209.   Par: ParList; (*actual parameters for next command*)
  2210.   User: ARRAY 8 OF CHAR; Password: LONGINT; (*current user*)
  2211.  
  2212.   CurFnt, CurCol:, CurOff SHORTINT; (*current font, color, vertical offset*)
  2213.  
  2214.    Arrow, Star: Marker;
  2215.    Mouse, Pointer: Cursor;
  2216.  
  2217.  (*user identification*)
  2218.  
  2219.   PROCEDURE SetUser (VAR user, password: ARRAY OF CHAR);
  2220.  
  2221.  (*clocks*)
  2222.  
  2223.   PROCEDURE GetClock (VAR t, d: LONGINT);
  2224.   PROCEDURE SetClock (t, d: LONGINT);
  2225.   PROCEDURE Time (): LONGINT; (*in units of 1/300 sec*)
  2226.  
  2227.  (*cursor handling*)
  2228.  
  2229.   PROCEDURE OpenCursor (VAR c: Cursor);
  2230.   PROCEDURE FadeCursor (VAR c: Cursor);
  2231.   PROCEDURE DrawCursor (VAR c: Cursor; VAR m: Marker; X, Y: INTEGER);
  2232.  
  2233.   (*display management*)
  2234.  
  2235.   PROCEDURE OpenDisplay (UW, SW, H: INTEGER);
  2236.     (*initialize new display with user track width UW, system track width
  2237.        SW, and height H*)
  2238.  
  2239.   PROCEDURE DisplayWidth (X: INTEGER): INTEGER;
  2240.     (*get width of display at X*)
  2241.  
  2242.   PROCEDURE DisplayHeight (X: INTEGER): INTEGER;
  2243.     (*get height of display at X*)
  2244.  
  2245.   PROCEDURE OpenTrack (X, W: INTEGER);
  2246.     (*open a new track of width W at X*)
  2247.  
  2248.   PROCEDURE UserTrack (X: INTEGER): INTEGER;
  2249.     (*get left margin of user track at X*)
  2250.  
  2251.   PROCEDURE SystemTrack (X: INTEGER): INTEGER;
  2252.     (*get left margin of system track at X*)
  2253.  
  2254.   PROCEDURE AllocateUserViewer (DX: INTEGER; VAR X, Y: INTEGER);
  2255.     (*allocate new user viewer within display at DX*)
  2256.  
  2257.   PROCEDURE AllocateSystemViewer (DX: INTEGER; VAR X, Y: INTEGER);
  2258.     (*allocate new system viewer within display at DX*)
  2259.  
  2260.   PROCEDURE PassFocus (V: Viewers.Viewer);
  2261.     (*pass focus to viewer V*)
  2262.  
  2263.   PROCEDURE RemoveMarks (X, Y, W, H: INTEGER);
  2264.     (*remove marks within given rectangle*)
  2265.  
  2266.   PROCEDURE MarkedViewer (): Viewers.Viewer;
  2267.     (*returns viewer marked by star-shaped pointer*)
  2268.  
  2269.  (*command interpretation*)
  2270.  
  2271.   PROCEDURE ShowMenu (VAR cmd: INTEGER;
  2272.                       X, Y: INTEGER;
  2273.                       menu: ARRAY OF CHAR);
  2274.     (* menu = {command "|"} command.
  2275.       Six commands allowed, 6 > cmd >= -1.
  2276.       cmd = 5: first command selected
  2277.       cmd = 0: last command selected
  2278.       cmd = -1: no selection *)
  2279.  
  2280.   PROCEDURE Call (VAR name: ARRAY OF CHAR;
  2281.                   par: ParList;
  2282.                   new: BOOLEAN;
  2283.                   VAR res: INTEGER);
  2284.     (*call command name and pass parameter list par. Option new requests
  2285.       loading of module.  Done = (res = 0)*)
  2286.  
  2287.   PROCEDURE GetSelection (VAR text: Texts.Text;
  2288.                           VAR beg, end, time: LONGINT);
  2289.    (*get most recent text selection. Text selection exists = (time >= 0)*)
  2290.  
  2291.  
  2292.   PROCEDURE Install (T: Task);
  2293.     (*install new task T*)
  2294.  
  2295.   PROCEDURE Remove (T: Task);
  2296.     (*remove installed task T*)
  2297.  
  2298.   PROCEDURE Collect;
  2299.     (*demand garbage collector*)
  2300.  
  2301.   PROCEDURE SetFont* (fnt: Fonts.Font);
  2302.     (*set current font*)
  2303.  
  2304.   PROCEDURE SetColor* (col: SHORTINT);
  2305.     (*set current color*)
  2306.  
  2307.   PROCEDURE SetOffset* (voff: SHORTINT);
  2308.     (*set current vertical offset*)
  2309.  
  2310. END Oberon. 
  2311.  
  2312.  
  2313. Remark; 
  2314.  
  2315. Installed tasks are considered to be background activities. They are activated 
  2316. by the central loop when no input events have been detected. For example, the
  2317. garbage collector is implemented as an installed task. Notice that installed
  2318. tasks may be invalidated after their host module has been unloaded (or replaced).
  2319. Unsafe tasks are automatically removed after a system trap in order to avoid 
  2320. an infinite repetition of the same error.
  2321.  
  2322. -------------------------------------------------------------------------- 
  2323.  
  2324.  
  2325. Tutorial Examples 
  2326.  
  2327.  
  2328. Write time stamp to system log 
  2329.  
  2330.  PROCEDURE TimeStamp;
  2331.  BEGIN
  2332.    Texts.WriteString(W, "TimeStamp ");
  2333.    Texts.WriteInt(W, Oberon.Time(), 1);
  2334.    Texts.WriteLn(W);
  2335.    Texts.Append(Oberon.Log, W.buf)
  2336.  END TimeStamp;
  2337.  
  2338. where 
  2339.  
  2340.  VAR
  2341.    W: Texts.Writer;
  2342.  
  2343. is globally defined initialized by Texts.OpenWriter(W).
  2344.  
  2345. Remarks: 
  2346.  
  2347. 1. Normally, one (global) writer per module is sufficient. 
  2348.  
  2349. 2. If you desire a specific part of the output text to appear in a new font, 
  2350.    for example in italics variant Syntax10i.Scn.Fnt, call
  2351.    Texts.SetFont(W,Fonts.This("Syntax10i.Scn.Fnt")) before writing this part
  2352.    and Texts.SetFont(W,Fonts.Default) before continuing to write ordinary text.
  2353.  
  2354.  
  2355. Process selected text 
  2356.  
  2357.  PROCEDURE CountWords;
  2358.  VAR
  2359.    T: Texts.Text;
  2360.    R: Texts.Reader;
  2361.    beg, end, pos, time: LONGINT;
  2362.    words: INTEGER; ch: CHAR;
  2363.  BEGIN
  2364.    words := 0;
  2365.    Oberon.GetSelection(T, beg, end, time); (*get most recent selection*)
  2366.    IF time >= 0 THEN (*if it exists*)
  2367.      Texts.OpenReader(R, T, beg);
  2368.      pos := beg; (*setup reader and initialize pos*)
  2369.      Texts.Read(R, ch);
  2370.      INC(pos); (*read next character*)
  2371.      IF (pos # end) & (ch > " ") THEN
  2372.        REPEAT
  2373.          Texts.Read(R, ch);
  2374.          INC(pos)
  2375.        UNTIL (pos = end) OR (ch <= " ");
  2376.        INC(words)
  2377.      END;
  2378.      WHILE pos # end DO
  2379.        (*(pos # end) & (ch <= " ")*)
  2380.        REPEAT
  2381.          Texts.Read(R, ch);
  2382.          INC(pos)
  2383.        UNTIL (pos = end) OR (ch > " ");
  2384.        IF pos # end THEN
  2385.          REPEAT
  2386.            Texts.Read(R, ch);
  2387.            INC(pos)
  2388.          UNTIL (pos = end) OR (ch <= "");
  2389.          INC(words)
  2390.        END;
  2391.      END;
  2392.    END;
  2393.    Texts.WriteString(W, "WordCount = ");
  2394.    Texts.WriteInt(W, words, 1);
  2395.    Texts.WriteLn(W);
  2396.    Texts.Append(Oberon.Log, W.buf) (*append to system log*)
  2397.  END CountWords;
  2398.  
  2399.  
  2400. where again 
  2401.  
  2402.  VAR
  2403.    W: Texts.Writer;
  2404.  
  2405. is globally defined and initialized by Texts.OpenWriter(W).
  2406.  
  2407.  
  2408. Open a viewer in system track, generate, and display text data 
  2409.  
  2410.  PROCEDURE Directory;
  2411.  VAR
  2412.    Menu, Main: TextFrames.Frame;
  2413.    T: Texts.Text; V: Viewers.Viewer;
  2414.    X, Y:INTEGER;
  2415.  BEGIN
  2416.    T := TextFrames.Text(""); (*generate new (and empty) text to be displayed
  2417.                                in a frame*)
  2418.    Menu := TextFrames.NewMenu("Directory", StandardMenu); (*generate standard menu frame*)
  2419.    Main := TextFrames.NewText(T, 0); (*generate standard text frame*)
  2420.    Oberon.AllocateSystemViewer(Oberon.Par.vwr.X, X, Y);
  2421.    V := MenuViewers.New(Menu, Main, TextFrames.menuH, X, Y); (*open standard menu viewer*)
  2422.    TextFrames.Mark(Main, -1); (*setup vertical arrow mark*)
  2423.    Diskette.Enumerate(Lister); (*pass over Lister-procedure to enumerator*)
  2424.    Texts.Append(T, W.buf); (*append writer to T and display written text*)
  2425.    TextFrames.Mark(Main, 1) (*restore position mark*)
  2426.  END Directory;
  2427.  
  2428.  
  2429. where
  2430.  
  2431.  CONST
  2432.    StandardMenu = "System.Close System.Copy System.Grow Edit.Search Edit.Store";
  2433.   VAR
  2434.     T: Texts.Text;
  2435.     W : Texts.Writer;
  2436.  
  2437. are globally defined, W is globally initialized by Texts.OpenWriter(W), and
  2438. Lister is an (upcalled) procedure displaying directory entries:
  2439.  
  2440.  PROCEDURE* Lister (name: ARRAY OF CHAR; date, time, size: LONGINT);
  2441.  BEGIN
  2442.    Texts.WriteString(W, name);
  2443.    Texts.Write(W, " ");
  2444.    Texts.WriteInt(W, size, 1);
  2445.    Texts.Write(W, " ");
  2446.    Texts.WriteDate(W, time, date);
  2447.    Texts.WriteLn(W)
  2448.  END Lister;
  2449.  
  2450.  
  2451. Remarks: 
  2452.  
  2453. 1. The above program generates its whole output text before displaying it. 
  2454. Alternatively, if you move the statement Texts.Append(T, W.buf) into the
  2455. Lister-procedure, every generated directory entry is displayed immediately.
  2456.  
  2457. 2. Oberon.AllocateSystemViewer(Oberon.Par.vwr.X, X, Y) is a standard proposal 
  2458.    for the placing of a new system viewer within the track from which the
  2459.    command was called. Of course, individual algorithms are possible as well.
  2460.    For example, if the new viewer is desired to cover the bottom most viewer,
  2461.    except if the pointer overrides this, the algorithm is
  2462.  
  2463.    PROCEDURE AllocateSystemViewer (DX: INTEGER; VAR X, Y: INTEGER);
  2464.    VAR
  2465.      bot: Viewers.Viewer;
  2466.    BEGIN
  2467.      IF Oberon.Pointer.on THEN
  2468.        X := Oberon.Pointer.X; Y := Oberon.Pointer.Y
  2469.      ELSE
  2470.        bot := Viewers.This(Oberon.SystemTrack(DX), 0);
  2471.      X := bot.X;
  2472.      Y := bot.H - Viewers.minH
  2473.      END
  2474.    END AllocateSystemViewer;
  2475.  
  2476. 3. TextFrames.NewText generates a standard text frame. The following statement 
  2477.    sequence produce a text frame with an individual handler and a customized
  2478.    geometry.
  2479.  
  2480.   NEW(F); Open(F, Handle, text, pos, col, left, right, top, bot, asr, dsr,lsp);
  2481.  
  2482. where F is of type TextFrames.Frame. 
  2483.  
  2484. Open a viewer in user track and display existing text 
  2485.  
  2486.  PROCEDURE OpenText;
  2487.  VAR
  2488.    par: Oberon.ParList;
  2489.    Text: TextFrames.Frame;
  2490.    S: Texts.Scanner;
  2491.    V: Viewers.Viewer;
  2492.    X, Y: INTEGER;
  2493.  BEGIN
  2494.    par := Oberon.Par; (*access parameters*)
  2495.    Text := par.frame(TextFrames.Frame); (*calling frame*)
  2496.    TextFrames.Mark(Text, -1); (*arrow mark*)
  2497.    Texts.OpenScanner(S, par.text, par.pos); (*open scanner at position of parameter list*)
  2498.    Texts.Scan(S); (*get symbol*)
  2499.    IF S.class = Texts.Name THEN
  2500.      Oberon.AllocateUserViewer(par.vwr.X, X, Y);
  2501.      V := MenuViewers.New(TextFrames.NewMenu(S.s, StandardMenu);
  2502.      TextFrames.NewText(TextFrames.Text(S.s), 0);
  2503.      TextFrames.menuH, X, Y);
  2504.    END;
  2505.    TextFrames.Mark(Text, 1) (*restore position mark*)
  2506.  END OpenText;
  2507.  
  2508.  
  2509. Remark: 
  2510.  
  2511. Oberon.AllocateUserViewer(par.vwr.X, X, Y) is a standard proposal for the 
  2512. placing of a new viewer in the caller's user track. Again, individual
  2513. algorithms are possible as well.
  2514.  
  2515.  
  2516. Grow viewer 
  2517.  
  2518.   PROCEDURE Grow;
  2519.   VAR
  2520.     V, newV: Viewers.Viewer;
  2521.     M: Oberon.CopyMsg;
  2522.     N: Viewers.ViewerMsg;
  2523.     DH: INTEGER;
  2524.   BEGIN
  2525.     V := Oberon.Par.vwr; (*get originator viewer*)
  2526.     DH := Oberon.DisplayHeight(V.X); (*get height of this track*)
  2527.     IF V.H < Oberon.DisplayHeight(V.X) THEN (*if viewer is small*)
  2528.       Oberon.OpenTrack(V.X, V.W); (*open overlaying track*)
  2529.       V.handle(V, M); newV := M.F(Viewers.Viewer); (*get a copy of the viewer*)
  2530.       Viewers.Open(newV, V.X, DH); (*open new big viewer*)
  2531.       N.id := Viewers.restore; newV.handle(newV, N) (*ask new viewer to draw itself*)
  2532.     END
  2533.   END Grow;
  2534.  
  2535.  
  2536.  Remark: 
  2537.  
  2538. The Grow command is generic in the sense that it can handle viewer instances
  2539. of any (current or future) class. Typically (and unavoidably) generic commands
  2540. use message passing instead of ordinary procedurecalls. This object-oriented
  2541. style will be explained in more detail in the next chapter. Also notice that
  2542. actually a copy of the original viewer is opened in the new track. When this 
  2543. track is being closed later, the original viewer will reappear.
  2544.  
  2545.  
  2546. Process viewer text or sequence of texts, depending on context 
  2547.  
  2548.  PROCEDURE ProcessText;
  2549.  VAR
  2550.    par: Oberon.ParList;
  2551.    Main: TextFrames.Frame;
  2552.    S: Texts.Scanner;
  2553.    T: Texts.Text;
  2554.  BEGIN
  2555.    par := Oberon.Par; (*access parameters*)
  2556.    IF par.frame = par.vwr.dsc THEN (*command in menu frame*)
  2557.      IF par.vwr.dsc.next IS TextFrames.Frame THEN
  2558.        Main := par.vwr.dsc.next(TextFrames.Frame); (*main text frame*)
  2559.        TextFrames.Mark(Main, -1) (*set arrow mark*)
  2560.        Process(Main.text); (*process displayed text*)
  2561.        TextFrames.Mark(Main, 1) (*restore position mark*)
  2562.      END
  2563.    ELSE (*command in main text frame*)
  2564.      Main := par.frame(TextFrames.Frame);
  2565.      TextFrames.Mark(Main, -1) (*set arrow mark*)
  2566.      Texts.OpenScanner(S, par.text, par.pos); (*open scanner at position of parameter list*)
  2567.      Texts.Scan(S); (*get first symbol*)
  2568.      WHILE S.class = Texts.Name DO
  2569.        Texts.Open(T, S.s); (*open text from file*)
  2570.        Process(T); (*process this text*)
  2571.        Texts.Scan(S) (*get next symbol*)
  2572.      END;
  2573.      TextFrames.Mark(Main, 1) (*restore position mark*)
  2574.    END
  2575.  END ProcessText;
  2576.  
  2577.  
  2578. Delete selected part of text in marked viewer 
  2579.  
  2580.  PROCEDURE Delete;
  2581.  VAR
  2582.    Main: TextFrames.Frame;
  2583.    V: Viewers.Viewer;
  2584.  BEGIN
  2585.    V := Oberon.MarkedViewer(); (*get marked viewer*)
  2586.    Main := V.dsc.next(TextFrames.Frame); (*main text frame of marked viewer*)
  2587.    IF Main.sel > 0 THEN (*if there exists a selection*)
  2588.      Texts.Delete(Main.text, Main.selbeg.pos, Main.selend.pos) (*delete text*)
  2589.    END
  2590.  END Delete;
  2591.  
  2592.  
  2593. Copy most recently selected text part to caret's position 
  2594.  
  2595.  PROCEDURE CopyText;
  2596.  VAR
  2597.    Main: TextFrames.Frame;
  2598.    buf: Texts.Buffer;
  2599.    V: Viewers.Viewer; time: LONGINT;
  2600.  BEGIN
  2601.    Oberon.GetSelection(T, beg, end, time); (*get most recent selection*)
  2602.    IF time >= 0 THEN (*if it exists*)
  2603.      Texts.OpenBuffer(buf);
  2604.      Texts.Save(T, beg, end, buf); (*save text in buffer*)
  2605.      V := Oberon.FocusViewer; (*get focus viewer*)
  2606.      IF (V.dsc # NIL) & (V.dsc.next IS TextFrames.Frame) THEN (*if text viewer*)
  2607.        Main := V.dsc.next(TextFrames.Frame); (*main text frame*)
  2608.        IF Main.car > 0 THEN (*if caret set*)
  2609.          Texts.Insert(Main.text, Main.carloc.pos, buf) (*insert text at caret's position*)
  2610.        END
  2611.      END
  2612.    END
  2613.  END CopyText;
  2614.  
  2615.  
  2616. Copy font from visibly marked position to text selection 
  2617.  
  2618.  PROCEDURE CopyFont;
  2619.  VAR
  2620.    F: TextFrames.Frame;
  2621.    T: Texts.Text;
  2622.    R: Texts.Reader;
  2623.    V: Viewers.Viewer;
  2624.    beg, end, time: LONGINT;
  2625.    X, Y: INTEGER; ch: CHAR;
  2626.  BEGIN
  2627.    Oberon.GetSelection(T, beg, end, time); (*get most recent selection*)
  2628.    IF (time >= 0) & Oberon.Pointer.on THEN (*if found and pointer visible*)
  2629.      X := Oberons.Pointer.X; Y := Oberon.Pointer.Y;
  2630.      V := Viewers.This(X, Y); (*marked viewer*)
  2631.      IF (V.dsc # NIL) & (V.dsc.next IS TextFrames.Frame) THEN
  2632.        F := V.dsc.next(TextFrames.Frame);
  2633.        IF (X >= F.X) & (X < F.X + F.W) & (Y >= F.Y) & (Y < F.Y + F.H) THEN
  2634.          Texts.OpenReader(R, F.text, TextFrames.Pos(F, X, Y)); (*position reader*)
  2635.          Texts.Read(R, ch); (*read marked char*)
  2636.          Texts.ChangeLooks(T, beg, end, {0}, R.fnt, 0, 0) (*change font alone*)
  2637.        END
  2638.      END
  2639.    END
  2640.  END CopyFont;
  2641.  
  2642.  
  2643. Move caret to next character written in italics 
  2644.  
  2645.  PROCEDURE SearchItalics;
  2646.  VAR
  2647.    Main: TextFrames.Frame;
  2648.    R: Texts.Reader; italic:
  2649.    Fonts.Font;
  2650.    V:Viewers.Viewer;
  2651.    pos: LONGINT; ch: CHAR;
  2652.  BEGIN
  2653.    italic := Fonts.This("Syntax10i.Scn.Fnt");
  2654.    V := Oberon.FocusViewer; (*get focus viewer*)
  2655.    IF (V.dsc # NIL) & (V.dsc.next IS TextFrames.Frame) THEN (*if text viewer*)
  2656.      Main := V.dsc.next(TextFrames.Frame); (*main text frame*)
  2657.      IF Main.car > 0 THEN (*if caret set*)
  2658.        Texts.OpenReader(R, Main.text, Main.carloc.pos); (*open reader at caret's position*)
  2659.        Texts.Read(R, ch);
  2660.        WHILE ~R.eot & (R.fnt # italic) DO
  2661.          Texts.Read(R, ch)
  2662.        END; (*read char stream*)
  2663.        IF ~R.eot THEN (*not end of text*)
  2664.          pos := Texts.Pos(R); (*reader's position*)
  2665.          TextFrames.RemoveSelection(Main); (*remove all marks*)
  2666.          TextFrames.RemoveCaret(Main);
  2667.          Oberon.RemoveMarks(Main.X, Main.Y, Main.W, Main.H);
  2668.          TextFrames.Show(Main, Max(0, pos - 200)); (*show text at pos*)
  2669.          TextFrames.SetCaret(Main, pos) (*set caret to new position*)
  2670.        END
  2671.      END
  2672.    END
  2673.  END SearchItalics;
  2674.  
  2675.  
  2676. where Max is the maximum-function.
  2677.  
  2678.  
  2679. Guide for Programmers of new Frame Classes and Viewer Types 
  2680.  
  2681.  
  2682. Frames as Active Objects 
  2683.  
  2684. Frames are the basic entities of Oberon's display system. They are 
  2685. more-or-less autonomous rectangular areas on the display screen and
  2686. may be nested. In particular, the display screen is hierarchically
  2687. organized like this: Display > tracks > viewers > data frames. Display, 
  2688. tracks, and viewers are entities to be managed by the viewer handler
  2689. module Viewers. Because of Oberon's tiling approach, all of these
  2690. frames are totally visible or totally invisible, i.e. there is no
  2691. partial overlapping on this level. There exists a class of standard
  2692. viewers called menu-viewers (and handled by module MenuViewers ).
  2693. Every menu-viewer contains exactly two vertically adjacent data frames:
  2694. A header frame (including title and menu) and a main data frame.
  2695. The main frame of a menu-viewer can be regarded as a virtual display
  2696. terminal representing the user interface to a certain application or
  2697. task. It may itself be nested, i.e. contain further subframes.
  2698. Because an individual command interpreter is associated with every frame,
  2699. implementing a new class of data frames is a most powerful way of adding 
  2700. functionality to the Oberon system.
  2701.  
  2702. We have intentionally used the term class. As a matter of fact, frames are
  2703. implemented in Oberon as active objects in the sense of object-oriented
  2704. programming. Calls of frame-specific handling procedures are made by
  2705. system routines in the form of message transfers. In particular, the
  2706. central Oberon loop typically initiates reactions on user-input actions
  2707. by sending appropriate messages to the respective viewers. We emphasize
  2708. that employing the object-oriented programming paradigm in connection with
  2709. the handling of frames is necessary in order to enable the kernel to call 
  2710. command interpreters whose identity is unknown to it.
  2711.  
  2712. Any handler that is associated with a certain viewer class, for example 
  2713. menu-viewers, is expected to handle messages from (at least) three different
  2714. originators: From the viewer manager, from the document manager, and from
  2715. the central loop. Messages from the viewer manager report on the state change
  2716. of the viewer. For example, the viewer manager Viewers sends a message whenever
  2717. a hidden viewer becomes visible (and must therefore restore its contents), or
  2718. when the size of a viewer has changed because its lower neighbour was opened,
  2719. changed, or closed. Messages from the document manager remind the viewer of
  2720. updating its contents after an editing operation.
  2721.  
  2722. Finally, messages from module Oberon notify the viewer of system-wide events,
  2723. such as input events (for example, "mouse button i pressed at position X, Y")
  2724. or an inquiry for the most recent text selection (regarded in Oberon as the
  2725. standard input ). The interpreter-part handling input events should be regarded
  2726. as an editor that is bound to the viewer class. In the case of viewers
  2727. displaying text, this is a text editor, in the case of graphics, it is a
  2728. graphics editor, and in the case of a viewer representing a mailbox it is
  2729. an editor for electronic mail.
  2730.  
  2731. A typical viewer handler (like the one associated with menu-viewers) processes 
  2732. viewer-oriented messages directly and delegates the handling of the more data-
  2733. specific messages by passing them on to the viewer's subframes. Prime examples
  2734. of viewer-oriented messages are requests to restore a viewer or change its size.
  2735. Examples of data-specific messages are selecting an object or invoking a
  2736. command by pointing to its name. Notice that new and finer-grained requests
  2737. may evolve from processing of viewer-oriented message.s For example, a request
  2738. to change the size of a menu-viewer is resolved in requests to change the size
  2739. of one or both of its subframes. In summarizing, viewer handlers normally act
  2740. both as mediators and originators of messages to be processed by the handlers
  2741. of their subframes.
  2742.  
  2743.  
  2744. The Canonical Decomposition of an Application 
  2745.  
  2746. Modularizing by separation of concerns is one of the most effective techniques 
  2747. applied to the design of large software systems. Our concept of a class of
  2748. frames displaying data of a certain kind provides a perfect opportunity to
  2749. demonstrate this technique. We can extract the following separate topics from
  2750. the program implementing an interactive application: the tool package, the
  2751. command interpreter, the display handler, and the data manager. The following
  2752. tasks are assigned to these parts: Providing a collection of powerful and
  2753. customized commands operating on the data of the given kind (tool package),
  2754. reacting on input actions within the associated display frame (command
  2755. interpreter), displaying the visible objects (display handler), and
  2756. encapsulating the management of the data without any concern of how they
  2757. are displayed (data manager). Typically, the data part comprises a set of
  2758. editing operations. It maintains an internal data structure describing the 
  2759. current state of the data. 
  2760.  
  2761. It is natural to try to assign a separate module to each of these parts. We 
  2762. soon see that the command interpreter part and the display manager are
  2763. preferably combined in one module because both need to operate on the same
  2764. associated display frame. This leads to the following canonical module
  2765. configurations in the casess of standard texts, graphics, pictures, and 
  2766. MyData, for example: 
  2767.  
  2768.  
  2769. Tool Package Edit Draw Paint MyTool Comm. Int. & Disp. Handler TextFrames
  2770. GraphicFrames PictureFrames MyFrames Data Manager Texts Graphics Pictures
  2771. MyData
  2772.  
  2773. Notice that the same data manager can in principle be used by different 
  2774. display handlers and command interpreters. Data managers serve as links
  2775. between different applications and thus enable an optimal integration.
  2776. For example, if the graphic system is based on module Texts for the
  2777. management of text captions, then text can freely be exchanged between
  2778. frames of these classes: Graphic frames and text frames are integrated.
  2779.  
  2780.                                                  1
  2781. Tutorial Example: Text Viewers 
  2782.  
  2783. So far, we have not explained yet how objects and messages are realized in the 
  2784. Oberon language. In contrast to typical object-oriented programming systems,
  2785. the complete set of messages understood by an object need not be specified
  2786. together with the definition of the object class. Instead, Oberon explores
  2787. a more flexible dual approach: Messages are typically defined in sender 
  2788. modules. For example, messages of the first of the above mentioned kinds
  2789. are defined in module Viewers, messages of the second kind are defined in
  2790. the respective editor module ( TextFrames in the case of text), and messages
  2791. of the third kind are defined in module Oberon which detects input events.
  2792.  
  2793. Roughly speaking, the Oberon language supports subclassing (by the
  2794. type extension facility), but messages and message handlers are not
  2795. institutionalized in the form of a language construct. We have
  2796. implemented the above outlined scheme by making use of procedure variables, 
  2797. and by applying Oberon's record extension facility to objects and to messages.
  2798.  
  2799. We shall now exemplify this model with the help of standard text-viewers,
  2800. i.e. menu-viewers whose subframes (menu and main) are text frames. The
  2801. following exposition may serve as a tutorial and template for implementors
  2802. of arbitrary frame classes or viewer types. We recall that the display data
  2803. structure is a hierarchy of display frames. Restricting our explanations to 
  2804. text-viewers we have the following hierarchy of types:
  2805.  
  2806.  
  2807. Viewers.Track MenuViewers.Viewer 
  2808.        ^ ^
  2809.  Viewers.Viewer TextFrames.Frame
  2810.             ^        ^
  2811.  
  2812.          Display.Frame
  2813.  
  2814. Module Display features the base types of frames and frame messages and the
  2815. type of the message handler. The (empty) base message serves as a root in the
  2816. (potentially unlimited) hierarchy of messages to be accepted by frames. Module
  2817. Viewers provides the definition of type Viewer, which is an extension (variant)
  2818. of type Display.Frame. Menu-viewers are a based on Viewers.Viewer an defined in
  2819. module MenuViewers.
  2820.  
  2821.  
  2822. In definition of Display: 
  2823.  
  2824.   TYPE
  2825.    Frame = POINTER TO FrameDesc;
  2826.    FrameMsg = RECORD
  2827.               END;
  2828.    Handler = PROCEDURE (Frame, VAR FrameMsg);
  2829.    FrameDesc = RECORD
  2830.                  dsc, next: Frame; (*son, brother*)
  2831.                  X, Y, W, H: INTEGER;
  2832.                  handle: Handler
  2833.                END;
  2834.  
  2835. In the definition of Viewers: 
  2836.  
  2837.   TYPE
  2838.    Viewer = POINTER TO ViewerDesc;
  2839.    ViewerDesc = RECORD
  2840.                   (Display.FrameDesc)
  2841.                   state: INTEGER
  2842.                 END;
  2843.  
  2844. In the definition of MenuViewers: 
  2845.  
  2846.   TYPE
  2847.    Viewer = POINTER TO ViewerDesc;
  2848.    ViewerDesc = RECORD
  2849.                   (Viewers.ViewerDesc)
  2850.                   menuH: INTEGER
  2851.                 END;
  2852.  
  2853. The following are the declarations of messages that are expected to be handled 
  2854. by every viewer. Note that they are distributed over several modules rather
  2855. than concentrated in one place (as it would be the case in an "ordinary"
  2856. object-oriented model).
  2857.  
  2858. In definition of Viewers: 
  2859.  
  2860.    ViewerMsg = RECORD (Display.FrameMsg)
  2861.                  id: INTEGER;
  2862.                  X, Y, W, H: INTEGER; (*new rectangle*)
  2863.                  state: INTEGER (*new state*)
  2864.                END;
  2865.    (*signals change of viewer state
  2866.     id = 0: restore viewer
  2867.          1: modify size at bottom
  2868.          2: suspend viewer*)
  2869.  
  2870. In definition of TextFrames: 
  2871.  
  2872.    UpdateMsg = RECORD (Display.FrameMsg)
  2873.                  id: INTEGER; (*operation*)
  2874.                  text: Texts.Text; (*edited text*)
  2875.                  beg, end: LONGINT (*stretch*)
  2876.                END;
  2877.    (*signals change of contents
  2878.      id = 0: stretch [beg, end[ replaced
  2879.           1: stretch [beg, end[ inserted
  2880.           2: stretch [beg, end[ deleted*)
  2881.  
  2882. In definition of Oberon: 
  2883.  
  2884.     InputMsg = RECORD (Display.FrameMsg)
  2885.                  id: INTEGER; (*operation*)
  2886.                  modes, keys: SET; (*mouse*)
  2887.                  X, Y: INTEGER; (*position*)
  2888.                  ch: CHAR (*character read*)
  2889.                END;
  2890.     (*signals input event
  2891.      id = 0: track mouse
  2892.           1: consume character*)
  2893.  
  2894.     ControlMsg = RECORD (Display.FrameMsg)
  2895.                    id: INTEGER; (*operation*)
  2896.                    X, Y: INTEGER (*current location of the mous*)
  2897.                  END;
  2898.  
  2899.      (*signals control action
  2900.        id = 0: remove focus
  2901.             1: remove all marks
  2902.             2: : mark*)
  2903.  
  2904.     SelectionMsg = RECORD (Display.FrameMsg)
  2905.                      time: LONGINT;
  2906.                      text: Texts.Text;
  2907.                      beg, end: LONGINT
  2908.                    END;
  2909.      (*signals inquiry for most recent text selection*)
  2910.  
  2911.      CopyOverMsg = RECORD (Display.FrameMsg)
  2912.                      text: Texts.Text;
  2913.                      beg, end: LONGINT
  2914.                    END;
  2915.      (*receive text stretch [beg, end[*)
  2916.  
  2917.      CopyMsg* = RECORD (Display.FrameMsg)
  2918.                   F: Display.Frame
  2919.                 END;
  2920.      (*request for the creation of a copy of a text frame*)
  2921.  
  2922. We recall that high-level viewer managers like MenuViewers typically pass on
  2923. most of the received messages to their subframes. In the course of (pre-)
  2924. processing viewer-oriented requests, high-level viewer managers can also
  2925. produce new messages. In the case of MenuViewers these are
  2926.  
  2927.   ModifyMsg* = RECORD (Display.FrameMsg)
  2928.                  id: INTEGER; (*operation*)
  2929.                  dY, Y, H: INTEGER (*vector dY, new Y and H*)
  2930.                END;
  2931.       (*vertically move and extend or reduce frame at bottom*)
  2932.         id = 0: extend frame
  2933.         id = 1: reduce frame*)
  2934.  
  2935. dY represents a vertical translation vector showing upwards in the extend-case
  2936. and showing downwards in the reduce-case. By definition, dY is always
  2937. non-negative. Y and H specify the new position and height respectively.
  2938. In summary, essentially the same messages have to be handled by a viewer and 
  2939. its subframes, except that some of the messages are processed or preprocessed
  2940. by the ancestor viewer already which, in turn, may result in sending new and
  2941. finer-grained messages to its subframes. A message is sent to a specific object
  2942. simply by calling its installed handler. For example, F.handle(F, M)
  2943. has the effect of sending message M to frame F. In case of text-frames, the
  2944. installed handler is Handle. It is elaborated in module TextFrames. We now
  2945. provide a tutorial sketch of this procedure. Notice that Handle makes
  2946. extensive use of Oberon's type test (and type guard) facility in order to
  2947. discriminate among the different message kinds.
  2948.  
  2949.  
  2950. 1  PROCEDURE Handle (F: Display.Frame; VAR M: Display.FrameMsg);
  2951. 2  VAR
  2952. 3    F1: Frame;
  2953. 4  BEGIN
  2954. 5    WITH F: Frame DO
  2955. 6      IF M IS Oberon.InputMsg THEN
  2956. 7        WITH M: Oberon.InputMsg DO
  2957. 8          IF M.id = Oberon.track THEN
  2958. 9            Edit(F, M.X, M.Y, M.keys)
  2959. 10         ELSIF
  2960. 11           M.id = Oberon.consume THEN
  2961. 12             IF F.car # 0 THEN
  2962. 13               Write(F, M.ch, M.fnt, M.col, M.voff)
  2963. 14             END
  2964. 15         END
  2965. 16       END
  2966. 17     ELSIF M IS Oberon.ControlMsg THEN
  2967. 18       WITH M: Oberon.ControlMsg DO
  2968. 19         IF M.id = Oberon.defocus THEN
  2969. 20           Defocus(F)
  2970. 21         ELSIF M.id = Oberon.neutralize THEN
  2971. 22           Neutralize(F)
  2972. 23         END
  2973. 24       END
  2974. 25     ELSIF M IS Oberon.SelectionMsg THEN
  2975. 26       WITH M: Oberon.SelectionMsg DO
  2976. 27         GetSelection(F, M.text, M.beg, M.end, M.time)
  2977. 28       END
  2978. 29     ELSIF M IS Oberon.CopyOverMsg THEN
  2979. 30       WITH M: Oberon.CopyOverMsg DO
  2980. 31         CopyOver(F, M.text, M.beg, M.end)
  2981. 32       END
  2982. 33     ELSIF M IS Oberon.CopyMsg THEN
  2983. 34       WITH M: Oberon.CopyMsg DO
  2984. 35         Copy(F, F1); M.F := F1
  2985. 36       END
  2986. 37     ELSIF M IS MenuViewers.ModifyMsg THEN
  2987. 38       WITH M: MenuViewers.ModifyMsg DO
  2988. 39         Modify(F, M.id, M.dY, M.Y, M.H)
  2989. 40       END
  2990. 41     ELSIF M IS UpdateMsg THEN
  2991. 42       WITH M: UpdateMsg DO
  2992. 43         IF F.text = M.text THEN
  2993. 44           Update(F, M)
  2994. 45         END
  2995. 46       END
  2996. 47     END
  2997. 48   END
  2998. 49 END Handle;
  2999.  
  3000.  
  3001. Explanations: 
  3002.  
  3003. 1  procedure of type Display.Handler
  3004. 2  auxiliary variable for frame copy (line 25). Needed because M.F is base type
  3005. 5  type guard; F must be a text frame
  3006. 6  type test; is message an Oberon input message?
  3007. 7  type guard
  3008. 8  if message demands mouse tracking
  3009. 11 if message demands consuming then consume a character
  3010. 12 if caret is active in this text frame
  3011. 17 type test; is message an Oberon control message?
  3012. 18 type guard
  3013. 19 if message demands removing the caret
  3014. 21 if message demands removing caret and selection
  3015. 25 type test; is message an Oberon selection inquiry?
  3016. 27 if so, register own selection if it is newer than candidate
  3017. 29 type test; is message a copy-over-message?
  3018. 31 if so, copy text stretch to caret's location in this frame
  3019. 33 type test; is message a copy-message?
  3020. 35 if so, produce a copy of this frame (initialized to empty)
  3021. 37 type test; is message a modify-message?
  3022. 39 if so, modify size or position of this frame (see below)
  3023. 41 type test; is message an update message?
  3024. 43 if so, check if changed text is represented in this frame and then update
  3025.    frame
  3026.  
  3027. We also provide the following refinement of the procedure TextFrames.Modify
  3028. called in line 37 in TextFrames.Handle. It shows well how subframes of menu-
  3029. viewers should react on a MenuViewers.ModifyMsg.
  3030.  
  3031.  PROCEDURE Modify (F: Frame; id, dY, Y, H: INTEGER);
  3032.  BEGIN
  3033.    Mark(F, 0);
  3034.    RemoveMarks(F); (*remove position-bar, caret, and selection*)
  3035.    IF id = MenuViewers.extend THEN
  3036.      IF dY > 0 THEN (*if frame is to be moved*)
  3037.        Display.CopyBlock(F.X, F.Y, F.W, F.H, F.X, F.Y + dY, 0); F.Y := F.Y + dY (*move original block*)
  3038.      END;
  3039.      Extend(F, Y) (*extend moved frame at its bottom*)
  3040.    ELSIF id = MenuViewers.reduce THEN
  3041.      Reduce(F, Y + dY); (*reduce original frame at its bottom*)
  3042.      IF dY > 0 THEN (*if frame is to be moved*)
  3043.        Display.CopyBlock(F.X, F.Y, F.W, F.H, F.X, Y, 0); F.Y := Y (*move reduced block*)
  3044.      END
  3045.    END;
  3046.    IF F.H > 0 THEN
  3047.      Mark(F, 1)
  3048.    END (*restore position-bar*)
  3049.  END Modify;
  3050.  
  3051. Remember that dY is always non-negative, and notice that the reduce-part of 
  3052. the procedure is the exact inverse of the extend-part.
  3053.  
  3054. Notice by the way that the above handler is used for the handling of both 
  3055. data-frames and standard header-frames. The two variants of text frames
  3056. differ only by their background color. This fact testifies for a streamlined
  3057. system design and is an example of the "today en-vogue" notion of code reusing.
  3058.  
  3059. The attentative and experienced reader may have noticed that the module
  3060. TextFrames plays two very different roles. Its first role is that of a
  3061. (late-bound) handler of messages sent to frame instances. The second role
  3062. is that of a library of procedures operating on text frames. Examples are
  3063. Edit, Write, CopyOverShow, SetCaret, and TrackWord. To the two roles of
  3064. TextFrames correspond two different ways of treating text frames, namely
  3065. as active objects individually reacting on messages, and as passive
  3066. rectangles to be operated on conventionally by invoking procedures.
  3067. The second way of treating frames might be of importance in cases
  3068. where text frames are text boxes belonging to the contents of some
  3069. more complex document. 
  3070.  
  3071. Module TextFrames offers yet another choice, this time to potential
  3072. implementors of handlers of subclasses of text frames: Either they
  3073. implement their own handler by just adding increments, and then
  3074. refer to Handle, or they compose an individual handler from the
  3075. elements. For example, a designer of MailFrames might apply the
  3076. first strategy. He might just add a few mail-oriented methods
  3077. catching the mail-oriented messages, and then delegate all
  3078. further processing to TextFrames.Handle. In contrast, an implementor
  3079. of a new user-interface to text frames might prefer strategy 2.
  3080.  
  3081. We conclude this section by explaining briefly the flow of control after,
  3082. for example, a character has been typed. We assume that the focus viewer
  3083. is a text viewer and that the caret is set in its main data frame.
  3084. First, the central loop Oberon detects the new character in the keyboard
  3085. buffer. It then sends an input consume-message to the focus-viewer which,
  3086. in turn, passes on this message to its main subframe.
  3087. After that, the handler (command interpreter) of this subframe locates the 
  3088. caret within the underlying text and subsequently calls the Insert-procedure
  3089. of the text data manager Texts. On that, Insert inserts the character in the
  3090. text and (up-)calls the associated notifier which, in our case, is residing
  3091. in TextFrames. The notifier then sends a broadcast-message of type
  3092. TextFrames.UpdateMsg to all visible viewers. Every single of these viewers
  3093. passes on this message to its subframes. If a subframe understands the
  3094. message and finds itself involved in this update, it restores its contents
  3095. by accessing the new data, again from the data manager Texts.
  3096.  
  3097. We now present some typical examples of implementations. 
  3098.  
  3099. Tutorial Examples 1: Frame oriented operations 
  3100.  
  3101. Display text line within text frame 
  3102.  
  3103.  PROCEDURE DisplayLine(F: Frame;
  3104.                        L: Line;
  3105.                        VAR R: Texts.Reader;
  3106.                        X, Y: INTEGER;
  3107.                        len: LONGINT);
  3108.  VAR
  3109.    pat: Display.Pattern;
  3110.    NX, dx, x, y, w, h: INTEGER;
  3111.  BEGIN
  3112.    NX := F.X + F.W;
  3113.    WHILE (nextCh # CarriageReturn) & (R.fnt # NIL) DO
  3114.      Display.GetChar(R.fnt.raster, nextCh, dx, x, y, w, h, pat);
  3115.      IF (X + x + w <= NX) & (h # 0) THEN
  3116.        Display.CopyPattern(R.col, pat, X + x, Y + y, 2)
  3117.      END;
  3118.      X := X + dx;
  3119.      INC(len); Texts.Read(R, nextCh)
  3120.    END;
  3121.    L.len := len + 1;
  3122.    L.wid := X + eolW - (F.X + F.margW);
  3123.    L.eot := R.fnt = NIL;
  3124.    Texts.Read(R, nextCh)
  3125.  END DisplayLine;
  3126.  
  3127. where the types Line and Frame are defined as follows. Notice that Line is
  3128. a private type and TextFrames.Frame is the public projection of type Frame.
  3129.  
  3130.  Line = POINTER TO LineDesc;
  3131.  LineDesc = RECORD
  3132.                len: LONGINT; (*number of characters in this line*)
  3133.                wid: INTEGER; (*width of line box*)
  3134.                eot: BOOLEAN; (*end of text flag*)
  3135.               next: Line (*next lower neighbour*)
  3136.             END;
  3137.  
  3138.  Location = RECORD
  3139.               org, pos: LONGINT; (*line origin, position*)
  3140.               dx, x, y: INTEGER; (*width and position of located character*)
  3141.               lin: Line (*associated line*)
  3142.             END;
  3143.  
  3144.  Frame = POINTER TO FrameDesc;
  3145.  FrameDesc = RECORD (Display.FrameDesc)
  3146.                text: Texts.Text; (*displayed text*)
  3147.                org: LONGINT; (*position in text of first displayed character*)
  3148.                col: INTEGER; (*background color*)
  3149.                lsp, asr, dsr: INTEGER; (*line spacing, ascender, descender*)
  3150.                left, right, top, bot: INTEGER; (*margins*)
  3151.                markH: INTEGER; (*margin width, position of mark*)
  3152.                time: LONGINT; (*time of latest selection*)
  3153.                mark, car, sel: INTEGER; (*state of mark, caret, selection*)
  3154.                carloc: Location; (*caret location*)
  3155.                selbeg, selend: Location (*locations of begin and end of selection*)
  3156.                trailer: Line (*pointer to the associated sequence of line descriptors*)
  3157.              END;
  3158.  
  3159.  
  3160. Track caret 
  3161.  
  3162.  PROCEDURE TrackCaret (F: Frame; X, Y: INTEGER; VAR keysum: SET);
  3163.  VAR
  3164.    loc: Location;
  3165.    keys: SET;
  3166.  BEGIN
  3167.    IF F.trailer.next # F.trailer THEN
  3168.      LocateChar(F, X - F.X, Y - F.Y, F.carloc);
  3169.      FlipCaret(F);
  3170.      keysum := {};
  3171.      LOOP
  3172.        Input.Mouse(keys, X, Y);
  3173.        IF keys = {} THEN
  3174.          EXIT
  3175.        END;
  3176.        keysum := keysum + keys;
  3177.        Oberon.DrawCursor(Oberon.Mouse, Oberon.Mouse.marker, X, Y);
  3178.        LocateChar(F, X - F.X, Y - F.Y, loc);
  3179.        IF loc.pos # F.carloc.pos THEN
  3180.          FlipCaret(F); F.carloc := loc;
  3181.          FlipCaret(F)
  3182.        END
  3183.      END;
  3184.      F.car := 1
  3185.    END
  3186.  END TrackCaret;
  3187.  
  3188.  
  3189.  
  3190. where the following auxiliary procedures are used: 
  3191.  
  3192.   PROCEDURE LocateChar (F: Frame; x, y: INTEGER; VAR loc: Location);
  3193.   VAR
  3194.     R: Texts.Reader;
  3195.     pat: Display.Pattern;
  3196.     pos, lim: LONGINT;
  3197.     ox, dx, u, v, w, h: INTEGER;
  3198.   BEGIN
  3199.     LocateLine(F, y, loc);
  3200.     lim := loc.org + loc.lin.len - 1;
  3201.     pos := loc.org;
  3202.     ox := F.left;
  3203.     Texts.OpenReader(R, F.text, loc.org);
  3204.     Texts.Read(R, nextCh);
  3205.     LOOP
  3206.       IF pos = lim THEN
  3207.         dx := eolW;
  3208.         EXIT
  3209.       END;
  3210.       Display.GetChar(R.fnt.raster, nextCh, dx, u, v, w, h, pat);
  3211.       IF ox + dx > x THEN
  3212.         EXIT
  3213.       END;
  3214.       INC(pos);
  3215.       ox := ox + dx;
  3216.       Texts.Read(R, nextCh)
  3217.     END;
  3218.     loc.pos := pos;
  3219.     loc.dx := dx;
  3220.     loc.x := ox
  3221.   END LocateChar;
  3222.  
  3223.  
  3224.  
  3225.  PROCEDURE LocateLine (F: Frame; y: INTEGER; VAR loc: Location);
  3226.  VAR
  3227.    T: Texts.Text;
  3228.    L: Line;
  3229.    org: LONGINT;
  3230.    cury: INTEGER;
  3231.  BEGIN
  3232.    T := F.text;
  3233.    org := F.org;
  3234.    L := F.trailer.next;
  3235.    cury := F.H - F.top - F.asr;
  3236.    WHILE (L.next # F.trailer) & (cury > y + F.dsr) DO
  3237.      org := org + L.len;
  3238.      L := L.next;
  3239.      cury := cury - F.lsp
  3240.    END;
  3241.    loc.org := org;
  3242.    loc.lin := L;
  3243.    loc.y := cury
  3244.  END LocateLine;
  3245.  
  3246.  
  3247.  
  3248.  PROCEDURE FlipCaret (F: Frame);
  3249.  BEGIN
  3250.    IF F.carloc.x < F.W THEN
  3251.      IF (F.carloc.y >= 10) & (F.carloc.x + 12 < F.W) THEN
  3252.        Display.CopyPattern(white, BigCaret, F.X + F.carloc.x, F.Y + F.carloc.y - 10, 2)
  3253.      ELSIF
  3254.        (F.carloc.y >= 4) & (F.carloc.x + 6 < F.W) THEN
  3255.          Display.CopyPattern(white, SmallCaret, F.X + F.carloc.x, F.Y + F.carloc.y - 4, 2)
  3256.      END
  3257.    END
  3258.  END FlipCaret;
  3259.  
  3260.  
  3261.  
  3262. Tutorial Examples 2: Text oriented operations 
  3263.  
  3264.  
  3265. Save text in buffer 
  3266.  
  3267.  PROCEDURE Save (T: Text; beg, end: LONGINT; B: Buffer);
  3268.  VAR
  3269.    p, q, qb, qe: Piece;
  3270.    org: LONGINT;
  3271.  BEGIN
  3272.    IF end > T.len THEN
  3273.      end := T.len
  3274.    END;
  3275.    FindPiece(T, beg, org, p);
  3276.    NEW(qb); qb^ := p^;
  3277.    qb.len := qb.len - (beg - org);
  3278.    qb.off := qb.off + (beg - org);
  3279.    qe := qb;
  3280.    WHILE end > org + p.len DO
  3281.      org := org + p.len;
  3282.      p := p.next;
  3283.      NEW(q); q^ := p^;
  3284.      qe.next := q;
  3285.      q.prev := qe;
  3286.      qe := q
  3287.    END;
  3288.    qe.next := NIL;
  3289.    qe.len := qe.len - (org + p.len - end);
  3290.    B.last.next := qb;
  3291.    qb.prev := B.last;
  3292.    B.last := qe;
  3293.    B.len := B.len + (end - beg)
  3294.  END Save;
  3295.  
  3296. where FindPiece is the following auxiliary procedure:
  3297.  
  3298.  PROCEDURE FindPiece (T: Text; pos: LONGINT; VAR org: LONGINT; VAR p: Piece);
  3299.  VAR
  3300.    n: INTEGER;
  3301.  BEGIN
  3302.    IF pos < T.org THEN
  3303.      T.org := -1;
  3304.      T.pce := T.trailer
  3305.    END;
  3306.    org := T.org;
  3307.    p := T.pce; (*from cache*)
  3308.    n := 0;
  3309.    WHILE pos >= org + p.len DO
  3310.      org := org + p.len;
  3311.      p := p.next;
  3312.      INC(n)
  3313.    END;
  3314.    IF n > 50 THEN
  3315.      T.org := org; T.pce := p
  3316.    END (*to cache*)
  3317.  END FindPiece;
  3318.  
  3319. and where the types Piece, Text, and Buffer are defined as follows.
  3320. Notice that Piece is a private type, Texts.Text is the public projection
  3321. of type Text, and Texts.Buffer is the public part of type Buffer.
  3322.  
  3323.  Piece = POINTER TO PieceDesc;
  3324.  PieceDesc = RECORD
  3325.                f: Files.File; (*carrier file*)
  3326.                off: LONGINT; (*offset in file*)
  3327.                len: LONGINT; (*piece length*)
  3328.                fnt: Fonts.Font; (*font*)
  3329.                col: SHORTINT; (*color*)
  3330.                voff: SHORTINT; (*vertical offset*)
  3331.                prev, next: Piece (*links to neighbours*)
  3332.              END;
  3333.  
  3334.   Text = POINTER TO TextDesc;
  3335.   Notifier = PROCEDURE (Text, INTEGER, LONGINT, LONGINT);
  3336.   TextDesc = RECORD
  3337.                len: LONGINT; (*text length*)
  3338.                notify: Notifier; (*called after text changes*)
  3339.                trailer: Piece; (*sentinel*)
  3340.                org: LONGINT; (*cached origin*)
  3341.                pce: Piece (*cached piece*)
  3342.              END;
  3343.  
  3344.  Buffer = POINTER TO BufDesc;
  3345.  BufDesc = RECORD
  3346.              len: LONGINT; (*buffer length*)
  3347.              header, last: Piece (*buffered piece list*)
  3348.            END;
  3349.  
  3350.  
  3351. Insert contents of buffer in text 
  3352.  
  3353.  PROCEDURE Insert (T: Text; pos: LONGINT; B: Buffer);
  3354.  VAR
  3355.    pl, pr, p, qb, qe: Piece;
  3356.    org: LONGINT;
  3357.  BEGIN
  3358.    FindPiece(T, pos, org, p);
  3359.    SplitPiece(p, pos - org, pr);
  3360.    IF T.org >= org THEN (*adjust cache*)
  3361.      T.org := org - p.prev.len;
  3362.      T.pce := p.prev
  3363.    END;
  3364.    pl := pr.prev;
  3365.    qb := B.header.next;
  3366.    IF (qb # NIL) & (qb.f = pl.f) & (qb.off = pl.off + pl.len) & (qb.fnt = pl.fnt) THEN
  3367.      pl.len := pl.len + qb.len;
  3368.      qb := qb.next
  3369.    END;
  3370.    IF qb # NIL THEN
  3371.      qe := B.last;
  3372.      qb.prev := pl;
  3373.      pl.next := qb;
  3374.      qe.next := pr;
  3375.      pr.prev := qe
  3376.    END;
  3377.    T.len := T.len + B.len;
  3378.    T.notify(T, insert, pos, pos + B.len); (*call postprocessor*)
  3379.    B.last := B.header;
  3380.    B.last.next := NIL;
  3381.    B.len := 0
  3382.  END Insert;
  3383.  
  3384. where SplitPiece is
  3385.  
  3386.  PROCEDURE SplitPiece (p: Piece; off: LONGINT; VAR pr: Piece); 
  3387.  VAR
  3388.    q: Piece;
  3389.  BEGIN
  3390.    IF off > 0 THEN
  3391.      NEW(q);
  3392.      q.col := p.col;
  3393.      q.fnt := p.fnt;
  3394.      q.len := p.len - off;
  3395.      q.f := p.f;
  3396.      q.off := p.off + off;
  3397.      p.len := off;
  3398.      q.next := p.next;
  3399.      p.next := q;
  3400.      q.prev := p;
  3401.      q.next.prev := q;
  3402.      pr := q
  3403.    ELSE
  3404.      pr := p
  3405.    END
  3406.  END SplitPiece; 
  3407.  
  3408.  
  3409. Literature 
  3410.  
  3411. Ceres Workstation 
  3412.  
  3413. H. Eberle. Development and Analysis of a Workstation Computer. 
  3414.   Diss. ETH No. 8431, 1987.
  3415.  
  3416. B. Heeb. Design of the Processor-Board for the Ceres-2 Workstation,
  3417.   Bericht 93, Inst. f ur Informatik, ETH Z urich, November 1988.
  3418.  
  3419.  
  3420. Oberon Language 
  3421.  
  3422. N. Wirth. Type Extensions. 
  3423.   ACM Trans. on Prog. Languages and Systems, 10, 2 (April 1988), 204-214.
  3424.  
  3425. N. Wirth. From Modula to Oberon. 
  3426.   Software - Practice and Experience, 18, 7, (July 1988), 661-670.
  3427.  
  3428. N. Wirth. The Programming Language Oberon. 
  3429.   Software - Practice and Experience, 18, 7, (July 1988), 671- 690.
  3430.  
  3431. J. Gutknecht. Variations on the Role of Module Interfaces. 
  3432.   Structured Programming, 10, 1, (Jan. 1989), 40-46.
  3433.  
  3434.  
  3435. Oberon System 
  3436.  
  3437. N. Wirth. An extensible system and a programming tool for workstation 
  3438.           computers. Proc. IVth South African Computer Science Symposium.
  3439.           Pretoria, SouthAfrica.
  3440.  
  3441. N. Wirth. Oberon: An Extensible Operating System for Workstations. 
  3442.   Proc. Euromicro Conf., Z urich, 29.8. - 1.9.1988.
  3443.  
  3444. N. Wirth and J. Gutknecht. The Oberon System.
  3445.   Bericht 88, Inst. f ur Informatik, ETH Z urich, July 1988,
  3446.   and Software - Practice and Experience, 19 (1989).
  3447.  
  3448. N. Wirth. Designing a System from Scratch. 
  3449.   Structured Programming, 10, 1 (Jan. 1989), 10-18.
  3450.  
  3451.  
  3452.